A small memory footprint AMQP implimentation
Dependents: iothub_client_sample_amqp remote_monitoring simplesample_amqp
link.c@46:01f7ca900e07, 2018-09-11 (annotated)
- Committer:
- AzureIoTClient
- Date:
- Tue Sep 11 11:13:43 2018 -0700
- Revision:
- 46:01f7ca900e07
- Parent:
- 44:9dd558f13109
1.2.9
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" |
AzureIoTClient | 36:8e1d94b0a70c | 18 | #include "azure_uamqp_c/async_operation.h" |
Azure.IoT Build | 0:6ae2f7bca550 | 19 | |
Azure.IoT Build | 0:6ae2f7bca550 | 20 | #define DEFAULT_LINK_CREDIT 10000 |
Azure.IoT Build | 0:6ae2f7bca550 | 21 | |
Azure.IoT Build | 0:6ae2f7bca550 | 22 | typedef struct DELIVERY_INSTANCE_TAG |
Azure.IoT Build | 0:6ae2f7bca550 | 23 | { |
AzureIoTClient | 28:add19eb7defa | 24 | delivery_number delivery_id; |
AzureIoTClient | 28:add19eb7defa | 25 | ON_DELIVERY_SETTLED on_delivery_settled; |
AzureIoTClient | 28:add19eb7defa | 26 | void* callback_context; |
AzureIoTClient | 28:add19eb7defa | 27 | void* link; |
AzureIoTClient | 34:6be9c2058664 | 28 | tickcounter_ms_t start_tick; |
AzureIoTClient | 34:6be9c2058664 | 29 | tickcounter_ms_t timeout; |
Azure.IoT Build | 0:6ae2f7bca550 | 30 | } DELIVERY_INSTANCE; |
Azure.IoT Build | 0:6ae2f7bca550 | 31 | |
AzureIoTClient | 43:4c1e4e94cdd3 | 32 | typedef struct ON_LINK_DETACH_EVENT_SUBSCRIPTION_TAG |
AzureIoTClient | 43:4c1e4e94cdd3 | 33 | { |
AzureIoTClient | 43:4c1e4e94cdd3 | 34 | ON_LINK_DETACH_RECEIVED on_link_detach_received; |
AzureIoTClient | 43:4c1e4e94cdd3 | 35 | void* context; |
AzureIoTClient | 43:4c1e4e94cdd3 | 36 | } ON_LINK_DETACH_EVENT_SUBSCRIPTION; |
AzureIoTClient | 43:4c1e4e94cdd3 | 37 | |
Azure.IoT Build | 0:6ae2f7bca550 | 38 | typedef struct LINK_INSTANCE_TAG |
Azure.IoT Build | 0:6ae2f7bca550 | 39 | { |
AzureIoTClient | 28:add19eb7defa | 40 | SESSION_HANDLE session; |
AzureIoTClient | 28:add19eb7defa | 41 | LINK_STATE link_state; |
AzureIoTClient | 28:add19eb7defa | 42 | LINK_STATE previous_link_state; |
AzureIoTClient | 28:add19eb7defa | 43 | AMQP_VALUE source; |
AzureIoTClient | 28:add19eb7defa | 44 | AMQP_VALUE target; |
AzureIoTClient | 28:add19eb7defa | 45 | handle handle; |
AzureIoTClient | 28:add19eb7defa | 46 | LINK_ENDPOINT_HANDLE link_endpoint; |
AzureIoTClient | 28:add19eb7defa | 47 | char* name; |
AzureIoTClient | 28:add19eb7defa | 48 | SINGLYLINKEDLIST_HANDLE pending_deliveries; |
AzureIoTClient | 28:add19eb7defa | 49 | sequence_no delivery_count; |
AzureIoTClient | 28:add19eb7defa | 50 | role role; |
AzureIoTClient | 28:add19eb7defa | 51 | ON_LINK_STATE_CHANGED on_link_state_changed; |
AzureIoTClient | 28:add19eb7defa | 52 | ON_LINK_FLOW_ON on_link_flow_on; |
Azure.IoT Build | 0:6ae2f7bca550 | 53 | ON_TRANSFER_RECEIVED on_transfer_received; |
AzureIoTClient | 28:add19eb7defa | 54 | void* callback_context; |
AzureIoTClient | 28:add19eb7defa | 55 | sender_settle_mode snd_settle_mode; |
AzureIoTClient | 28:add19eb7defa | 56 | receiver_settle_mode rcv_settle_mode; |
AzureIoTClient | 28:add19eb7defa | 57 | sequence_no initial_delivery_count; |
AzureIoTClient | 28:add19eb7defa | 58 | uint64_t max_message_size; |
AzureIoTClient | 28:add19eb7defa | 59 | uint64_t peer_max_message_size; |
AzureIoTClient | 41:0e723f9cbd89 | 60 | uint32_t current_link_credit; |
AzureIoTClient | 41:0e723f9cbd89 | 61 | uint32_t max_link_credit; |
AzureIoTClient | 28:add19eb7defa | 62 | uint32_t available; |
Azure.IoT Build | 0:6ae2f7bca550 | 63 | fields attach_properties; |
AzureIoTClient | 12:b30dacf113f2 | 64 | bool is_underlying_session_begun; |
AzureIoTClient | 12:b30dacf113f2 | 65 | bool is_closed; |
AzureIoTClient | 12:b30dacf113f2 | 66 | unsigned char* received_payload; |
AzureIoTClient | 12:b30dacf113f2 | 67 | uint32_t received_payload_size; |
AzureIoTClient | 12:b30dacf113f2 | 68 | delivery_number received_delivery_id; |
AzureIoTClient | 34:6be9c2058664 | 69 | TICK_COUNTER_HANDLE tick_counter; |
AzureIoTClient | 43:4c1e4e94cdd3 | 70 | ON_LINK_DETACH_EVENT_SUBSCRIPTION on_link_detach_received_event_subscription; |
Azure.IoT Build | 0:6ae2f7bca550 | 71 | } LINK_INSTANCE; |
Azure.IoT Build | 0:6ae2f7bca550 | 72 | |
AzureIoTClient | 36:8e1d94b0a70c | 73 | DEFINE_ASYNC_OPERATION_CONTEXT(DELIVERY_INSTANCE); |
AzureIoTClient | 36:8e1d94b0a70c | 74 | |
Azure.IoT Build | 0:6ae2f7bca550 | 75 | static void set_link_state(LINK_INSTANCE* link_instance, LINK_STATE link_state) |
Azure.IoT Build | 0:6ae2f7bca550 | 76 | { |
AzureIoTClient | 28:add19eb7defa | 77 | link_instance->previous_link_state = link_instance->link_state; |
AzureIoTClient | 28:add19eb7defa | 78 | link_instance->link_state = link_state; |
Azure.IoT Build | 0:6ae2f7bca550 | 79 | |
AzureIoTClient | 28:add19eb7defa | 80 | if (link_instance->on_link_state_changed != NULL) |
AzureIoTClient | 28:add19eb7defa | 81 | { |
AzureIoTClient | 28:add19eb7defa | 82 | link_instance->on_link_state_changed(link_instance->callback_context, link_state, link_instance->previous_link_state); |
AzureIoTClient | 28:add19eb7defa | 83 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 84 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 85 | |
AzureIoTClient | 21:f9c433d8e6ca | 86 | static void remove_all_pending_deliveries(LINK_INSTANCE* link, bool indicate_settled) |
AzureIoTClient | 21:f9c433d8e6ca | 87 | { |
AzureIoTClient | 21:f9c433d8e6ca | 88 | if (link->pending_deliveries != NULL) |
AzureIoTClient | 21:f9c433d8e6ca | 89 | { |
AzureIoTClient | 21:f9c433d8e6ca | 90 | LIST_ITEM_HANDLE item = singlylinkedlist_get_head_item(link->pending_deliveries); |
AzureIoTClient | 21:f9c433d8e6ca | 91 | while (item != NULL) |
AzureIoTClient | 21:f9c433d8e6ca | 92 | { |
AzureIoTClient | 21:f9c433d8e6ca | 93 | LIST_ITEM_HANDLE next_item = singlylinkedlist_get_next_item(item); |
AzureIoTClient | 36:8e1d94b0a70c | 94 | ASYNC_OPERATION_HANDLE pending_delivery_operation = (ASYNC_OPERATION_HANDLE)singlylinkedlist_item_get_value(item); |
AzureIoTClient | 36:8e1d94b0a70c | 95 | if (pending_delivery_operation != NULL) |
AzureIoTClient | 21:f9c433d8e6ca | 96 | { |
AzureIoTClient | 36:8e1d94b0a70c | 97 | DELIVERY_INSTANCE* delivery_instance = (DELIVERY_INSTANCE*)GET_ASYNC_OPERATION_CONTEXT(DELIVERY_INSTANCE, pending_delivery_operation); |
AzureIoTClient | 21:f9c433d8e6ca | 98 | if (indicate_settled && (delivery_instance->on_delivery_settled != NULL)) |
AzureIoTClient | 21:f9c433d8e6ca | 99 | { |
AzureIoTClient | 23:1111ee8bcba4 | 100 | delivery_instance->on_delivery_settled(delivery_instance->callback_context, delivery_instance->delivery_id, LINK_DELIVERY_SETTLE_REASON_NOT_DELIVERED, NULL); |
AzureIoTClient | 21:f9c433d8e6ca | 101 | } |
AzureIoTClient | 36:8e1d94b0a70c | 102 | |
AzureIoTClient | 36:8e1d94b0a70c | 103 | async_operation_destroy(pending_delivery_operation); |
AzureIoTClient | 21:f9c433d8e6ca | 104 | } |
AzureIoTClient | 21:f9c433d8e6ca | 105 | |
AzureIoTClient | 21:f9c433d8e6ca | 106 | item = next_item; |
AzureIoTClient | 21:f9c433d8e6ca | 107 | } |
AzureIoTClient | 21:f9c433d8e6ca | 108 | |
AzureIoTClient | 21:f9c433d8e6ca | 109 | singlylinkedlist_destroy(link->pending_deliveries); |
AzureIoTClient | 21:f9c433d8e6ca | 110 | link->pending_deliveries = NULL; |
AzureIoTClient | 21:f9c433d8e6ca | 111 | } |
AzureIoTClient | 21:f9c433d8e6ca | 112 | } |
AzureIoTClient | 21:f9c433d8e6ca | 113 | |
Azure.IoT Build | 0:6ae2f7bca550 | 114 | static int send_flow(LINK_INSTANCE* link) |
Azure.IoT Build | 0:6ae2f7bca550 | 115 | { |
AzureIoTClient | 28:add19eb7defa | 116 | int result; |
AzureIoTClient | 28:add19eb7defa | 117 | FLOW_HANDLE flow = flow_create(0, 0, 0); |
Azure.IoT Build | 0:6ae2f7bca550 | 118 | |
AzureIoTClient | 28:add19eb7defa | 119 | if (flow == NULL) |
AzureIoTClient | 28:add19eb7defa | 120 | { |
AzureIoTClient | 41:0e723f9cbd89 | 121 | LogError("NULL flow performative"); |
AzureIoTClient | 28:add19eb7defa | 122 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 123 | } |
AzureIoTClient | 28:add19eb7defa | 124 | else |
AzureIoTClient | 28:add19eb7defa | 125 | { |
AzureIoTClient | 41:0e723f9cbd89 | 126 | if (flow_set_link_credit(flow, link->current_link_credit) != 0) |
AzureIoTClient | 41:0e723f9cbd89 | 127 | { |
AzureIoTClient | 41:0e723f9cbd89 | 128 | LogError("Cannot set link credit on flow performative"); |
AzureIoTClient | 41:0e723f9cbd89 | 129 | result = __FAILURE__; |
AzureIoTClient | 41:0e723f9cbd89 | 130 | } |
AzureIoTClient | 41:0e723f9cbd89 | 131 | else if (flow_set_handle(flow, link->handle) != 0) |
AzureIoTClient | 28:add19eb7defa | 132 | { |
AzureIoTClient | 41:0e723f9cbd89 | 133 | LogError("Cannot set handle on flow performative"); |
AzureIoTClient | 41:0e723f9cbd89 | 134 | result = __FAILURE__; |
AzureIoTClient | 41:0e723f9cbd89 | 135 | } |
AzureIoTClient | 41:0e723f9cbd89 | 136 | else if (flow_set_delivery_count(flow, link->delivery_count) != 0) |
AzureIoTClient | 41:0e723f9cbd89 | 137 | { |
AzureIoTClient | 41:0e723f9cbd89 | 138 | LogError("Cannot set delivery count on flow performative"); |
AzureIoTClient | 28:add19eb7defa | 139 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 140 | } |
AzureIoTClient | 28:add19eb7defa | 141 | else |
AzureIoTClient | 28:add19eb7defa | 142 | { |
AzureIoTClient | 28:add19eb7defa | 143 | if (session_send_flow(link->link_endpoint, flow) != 0) |
AzureIoTClient | 28:add19eb7defa | 144 | { |
AzureIoTClient | 41:0e723f9cbd89 | 145 | LogError("Sending flow frame failed in session send"); |
AzureIoTClient | 28:add19eb7defa | 146 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 147 | } |
AzureIoTClient | 28:add19eb7defa | 148 | else |
AzureIoTClient | 28:add19eb7defa | 149 | { |
AzureIoTClient | 28:add19eb7defa | 150 | result = 0; |
AzureIoTClient | 28:add19eb7defa | 151 | } |
AzureIoTClient | 28:add19eb7defa | 152 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 153 | |
AzureIoTClient | 28:add19eb7defa | 154 | flow_destroy(flow); |
AzureIoTClient | 28:add19eb7defa | 155 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 156 | |
AzureIoTClient | 28:add19eb7defa | 157 | return result; |
Azure.IoT Build | 0:6ae2f7bca550 | 158 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 159 | |
Azure.IoT Build | 0:6ae2f7bca550 | 160 | static int send_disposition(LINK_INSTANCE* link_instance, delivery_number delivery_number, AMQP_VALUE delivery_state) |
Azure.IoT Build | 0:6ae2f7bca550 | 161 | { |
AzureIoTClient | 28:add19eb7defa | 162 | int result; |
Azure.IoT Build | 0:6ae2f7bca550 | 163 | |
AzureIoTClient | 28:add19eb7defa | 164 | DISPOSITION_HANDLE disposition = disposition_create(link_instance->role, delivery_number); |
AzureIoTClient | 28:add19eb7defa | 165 | if (disposition == NULL) |
AzureIoTClient | 28:add19eb7defa | 166 | { |
AzureIoTClient | 41:0e723f9cbd89 | 167 | LogError("NULL disposition performative"); |
AzureIoTClient | 28:add19eb7defa | 168 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 169 | } |
AzureIoTClient | 28:add19eb7defa | 170 | else |
AzureIoTClient | 28:add19eb7defa | 171 | { |
AzureIoTClient | 41:0e723f9cbd89 | 172 | if (disposition_set_last(disposition, delivery_number) != 0) |
AzureIoTClient | 41:0e723f9cbd89 | 173 | { |
AzureIoTClient | 41:0e723f9cbd89 | 174 | LogError("Failed setting last on disposition performative"); |
AzureIoTClient | 41:0e723f9cbd89 | 175 | result = __FAILURE__; |
AzureIoTClient | 41:0e723f9cbd89 | 176 | } |
AzureIoTClient | 41:0e723f9cbd89 | 177 | else if (disposition_set_settled(disposition, true) != 0) |
AzureIoTClient | 28:add19eb7defa | 178 | { |
AzureIoTClient | 41:0e723f9cbd89 | 179 | LogError("Failed setting settled on disposition performative"); |
AzureIoTClient | 41:0e723f9cbd89 | 180 | result = __FAILURE__; |
AzureIoTClient | 41:0e723f9cbd89 | 181 | } |
AzureIoTClient | 41:0e723f9cbd89 | 182 | else if ((delivery_state != NULL) && (disposition_set_state(disposition, delivery_state) != 0)) |
AzureIoTClient | 41:0e723f9cbd89 | 183 | { |
AzureIoTClient | 41:0e723f9cbd89 | 184 | LogError("Failed setting state on disposition performative"); |
AzureIoTClient | 28:add19eb7defa | 185 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 186 | } |
AzureIoTClient | 28:add19eb7defa | 187 | else |
AzureIoTClient | 28:add19eb7defa | 188 | { |
AzureIoTClient | 28:add19eb7defa | 189 | if (session_send_disposition(link_instance->link_endpoint, disposition) != 0) |
AzureIoTClient | 28:add19eb7defa | 190 | { |
AzureIoTClient | 41:0e723f9cbd89 | 191 | LogError("Sending disposition failed in session send"); |
AzureIoTClient | 28:add19eb7defa | 192 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 193 | } |
AzureIoTClient | 28:add19eb7defa | 194 | else |
AzureIoTClient | 28:add19eb7defa | 195 | { |
AzureIoTClient | 28:add19eb7defa | 196 | result = 0; |
AzureIoTClient | 28:add19eb7defa | 197 | } |
AzureIoTClient | 28:add19eb7defa | 198 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 199 | |
AzureIoTClient | 28:add19eb7defa | 200 | disposition_destroy(disposition); |
AzureIoTClient | 28:add19eb7defa | 201 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 202 | |
AzureIoTClient | 28:add19eb7defa | 203 | return result; |
Azure.IoT Build | 0:6ae2f7bca550 | 204 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 205 | |
AzureIoTClient | 12:b30dacf113f2 | 206 | static int send_detach(LINK_INSTANCE* link_instance, bool close, ERROR_HANDLE error_handle) |
Azure.IoT Build | 0:6ae2f7bca550 | 207 | { |
AzureIoTClient | 28:add19eb7defa | 208 | int result; |
AzureIoTClient | 28:add19eb7defa | 209 | DETACH_HANDLE detach_performative; |
Azure.IoT Build | 0:6ae2f7bca550 | 210 | |
AzureIoTClient | 28:add19eb7defa | 211 | detach_performative = detach_create(0); |
AzureIoTClient | 28:add19eb7defa | 212 | if (detach_performative == NULL) |
AzureIoTClient | 28:add19eb7defa | 213 | { |
AzureIoTClient | 41:0e723f9cbd89 | 214 | LogError("NULL detach performative"); |
AzureIoTClient | 28:add19eb7defa | 215 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 216 | } |
AzureIoTClient | 28:add19eb7defa | 217 | else |
AzureIoTClient | 28:add19eb7defa | 218 | { |
AzureIoTClient | 28:add19eb7defa | 219 | if ((error_handle != NULL) && |
AzureIoTClient | 28:add19eb7defa | 220 | (detach_set_error(detach_performative, error_handle) != 0)) |
AzureIoTClient | 28:add19eb7defa | 221 | { |
AzureIoTClient | 41:0e723f9cbd89 | 222 | LogError("Failed setting error on detach frame"); |
AzureIoTClient | 28:add19eb7defa | 223 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 224 | } |
AzureIoTClient | 12:b30dacf113f2 | 225 | else if (close && |
AzureIoTClient | 12:b30dacf113f2 | 226 | (detach_set_closed(detach_performative, true) != 0)) |
AzureIoTClient | 12:b30dacf113f2 | 227 | { |
AzureIoTClient | 41:0e723f9cbd89 | 228 | LogError("Failed setting closed field on detach frame"); |
AzureIoTClient | 19:000ab4e6a2c1 | 229 | result = __FAILURE__; |
AzureIoTClient | 12:b30dacf113f2 | 230 | } |
AzureIoTClient | 12:b30dacf113f2 | 231 | else |
AzureIoTClient | 28:add19eb7defa | 232 | { |
AzureIoTClient | 28:add19eb7defa | 233 | if (session_send_detach(link_instance->link_endpoint, detach_performative) != 0) |
AzureIoTClient | 28:add19eb7defa | 234 | { |
AzureIoTClient | 41:0e723f9cbd89 | 235 | LogError("Sending detach frame failed in session send"); |
AzureIoTClient | 28:add19eb7defa | 236 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 237 | } |
AzureIoTClient | 28:add19eb7defa | 238 | else |
AzureIoTClient | 28:add19eb7defa | 239 | { |
AzureIoTClient | 12:b30dacf113f2 | 240 | if (close) |
AzureIoTClient | 12:b30dacf113f2 | 241 | { |
AzureIoTClient | 12:b30dacf113f2 | 242 | /* Declare link to be closed */ |
AzureIoTClient | 12:b30dacf113f2 | 243 | link_instance->is_closed = true; |
AzureIoTClient | 12:b30dacf113f2 | 244 | } |
AzureIoTClient | 12:b30dacf113f2 | 245 | |
AzureIoTClient | 28:add19eb7defa | 246 | result = 0; |
AzureIoTClient | 28:add19eb7defa | 247 | } |
AzureIoTClient | 28:add19eb7defa | 248 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 249 | |
AzureIoTClient | 28:add19eb7defa | 250 | detach_destroy(detach_performative); |
AzureIoTClient | 28:add19eb7defa | 251 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 252 | |
AzureIoTClient | 28:add19eb7defa | 253 | return result; |
Azure.IoT Build | 0:6ae2f7bca550 | 254 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 255 | |
AzureIoTClient | 12:b30dacf113f2 | 256 | static int send_attach(LINK_INSTANCE* link, const char* name, handle handle, role role) |
AzureIoTClient | 12:b30dacf113f2 | 257 | { |
AzureIoTClient | 12:b30dacf113f2 | 258 | int result; |
AzureIoTClient | 12:b30dacf113f2 | 259 | ATTACH_HANDLE attach = attach_create(name, handle, role); |
AzureIoTClient | 12:b30dacf113f2 | 260 | |
AzureIoTClient | 12:b30dacf113f2 | 261 | if (attach == NULL) |
AzureIoTClient | 12:b30dacf113f2 | 262 | { |
AzureIoTClient | 41:0e723f9cbd89 | 263 | LogError("NULL attach performative"); |
AzureIoTClient | 19:000ab4e6a2c1 | 264 | result = __FAILURE__; |
AzureIoTClient | 12:b30dacf113f2 | 265 | } |
AzureIoTClient | 12:b30dacf113f2 | 266 | else |
AzureIoTClient | 12:b30dacf113f2 | 267 | { |
AzureIoTClient | 12:b30dacf113f2 | 268 | result = 0; |
AzureIoTClient | 12:b30dacf113f2 | 269 | |
AzureIoTClient | 12:b30dacf113f2 | 270 | link->delivery_count = link->initial_delivery_count; |
AzureIoTClient | 12:b30dacf113f2 | 271 | |
AzureIoTClient | 12:b30dacf113f2 | 272 | attach_set_snd_settle_mode(attach, link->snd_settle_mode); |
AzureIoTClient | 12:b30dacf113f2 | 273 | attach_set_rcv_settle_mode(attach, link->rcv_settle_mode); |
AzureIoTClient | 12:b30dacf113f2 | 274 | attach_set_role(attach, role); |
AzureIoTClient | 12:b30dacf113f2 | 275 | attach_set_source(attach, link->source); |
AzureIoTClient | 12:b30dacf113f2 | 276 | attach_set_target(attach, link->target); |
AzureIoTClient | 23:1111ee8bcba4 | 277 | if (link->attach_properties != NULL) |
AzureIoTClient | 23:1111ee8bcba4 | 278 | { |
AzureIoTClient | 41:0e723f9cbd89 | 279 | (void)attach_set_properties(attach, link->attach_properties); |
AzureIoTClient | 23:1111ee8bcba4 | 280 | } |
AzureIoTClient | 12:b30dacf113f2 | 281 | |
AzureIoTClient | 12:b30dacf113f2 | 282 | if (role == role_sender) |
AzureIoTClient | 12:b30dacf113f2 | 283 | { |
AzureIoTClient | 12:b30dacf113f2 | 284 | if (attach_set_initial_delivery_count(attach, link->delivery_count) != 0) |
AzureIoTClient | 12:b30dacf113f2 | 285 | { |
AzureIoTClient | 41:0e723f9cbd89 | 286 | LogError("Cannot set attach initial delivery count"); |
AzureIoTClient | 19:000ab4e6a2c1 | 287 | result = __FAILURE__; |
AzureIoTClient | 12:b30dacf113f2 | 288 | } |
AzureIoTClient | 12:b30dacf113f2 | 289 | } |
AzureIoTClient | 12:b30dacf113f2 | 290 | |
AzureIoTClient | 12:b30dacf113f2 | 291 | if (result == 0) |
AzureIoTClient | 12:b30dacf113f2 | 292 | { |
AzureIoTClient | 41:0e723f9cbd89 | 293 | if (attach_set_max_message_size(attach, link->max_message_size) != 0) |
AzureIoTClient | 12:b30dacf113f2 | 294 | { |
AzureIoTClient | 41:0e723f9cbd89 | 295 | LogError("Cannot set max message size"); |
AzureIoTClient | 41:0e723f9cbd89 | 296 | result = __FAILURE__; |
AzureIoTClient | 41:0e723f9cbd89 | 297 | } |
AzureIoTClient | 41:0e723f9cbd89 | 298 | else if (session_send_attach(link->link_endpoint, attach) != 0) |
AzureIoTClient | 41:0e723f9cbd89 | 299 | { |
AzureIoTClient | 41:0e723f9cbd89 | 300 | LogError("Sending attach failed in session send"); |
AzureIoTClient | 19:000ab4e6a2c1 | 301 | result = __FAILURE__; |
AzureIoTClient | 12:b30dacf113f2 | 302 | } |
AzureIoTClient | 12:b30dacf113f2 | 303 | else |
AzureIoTClient | 12:b30dacf113f2 | 304 | { |
AzureIoTClient | 12:b30dacf113f2 | 305 | result = 0; |
AzureIoTClient | 12:b30dacf113f2 | 306 | } |
AzureIoTClient | 12:b30dacf113f2 | 307 | } |
AzureIoTClient | 12:b30dacf113f2 | 308 | |
AzureIoTClient | 12:b30dacf113f2 | 309 | attach_destroy(attach); |
AzureIoTClient | 12:b30dacf113f2 | 310 | } |
AzureIoTClient | 12:b30dacf113f2 | 311 | |
AzureIoTClient | 12:b30dacf113f2 | 312 | return result; |
AzureIoTClient | 12:b30dacf113f2 | 313 | } |
AzureIoTClient | 12:b30dacf113f2 | 314 | |
Azure.IoT Build | 0:6ae2f7bca550 | 315 | static void link_frame_received(void* context, AMQP_VALUE performative, uint32_t payload_size, const unsigned char* payload_bytes) |
Azure.IoT Build | 0:6ae2f7bca550 | 316 | { |
AzureIoTClient | 28:add19eb7defa | 317 | LINK_INSTANCE* link_instance = (LINK_INSTANCE*)context; |
AzureIoTClient | 28:add19eb7defa | 318 | AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(performative); |
Azure.IoT Build | 0:6ae2f7bca550 | 319 | |
AzureIoTClient | 28:add19eb7defa | 320 | if (is_attach_type_by_descriptor(descriptor)) |
AzureIoTClient | 28:add19eb7defa | 321 | { |
AzureIoTClient | 28:add19eb7defa | 322 | ATTACH_HANDLE attach_handle; |
AzureIoTClient | 24:2c59c2d43ebf | 323 | |
AzureIoTClient | 41:0e723f9cbd89 | 324 | if (amqpvalue_get_attach(performative, &attach_handle) != 0) |
AzureIoTClient | 41:0e723f9cbd89 | 325 | { |
AzureIoTClient | 41:0e723f9cbd89 | 326 | LogError("Cannot get attach performative"); |
AzureIoTClient | 41:0e723f9cbd89 | 327 | } |
AzureIoTClient | 41:0e723f9cbd89 | 328 | else |
AzureIoTClient | 28:add19eb7defa | 329 | { |
AzureIoTClient | 28:add19eb7defa | 330 | if ((link_instance->role == role_receiver) && |
AzureIoTClient | 28:add19eb7defa | 331 | (attach_get_initial_delivery_count(attach_handle, &link_instance->delivery_count) != 0)) |
AzureIoTClient | 28:add19eb7defa | 332 | { |
AzureIoTClient | 41:0e723f9cbd89 | 333 | LogError("Cannot get initial delivery count"); |
AzureIoTClient | 29:4a11413cf217 | 334 | remove_all_pending_deliveries(link_instance, true); |
AzureIoTClient | 28:add19eb7defa | 335 | set_link_state(link_instance, LINK_STATE_DETACHED); |
AzureIoTClient | 28:add19eb7defa | 336 | } |
AzureIoTClient | 28:add19eb7defa | 337 | else |
AzureIoTClient | 28:add19eb7defa | 338 | { |
AzureIoTClient | 28:add19eb7defa | 339 | if (attach_get_max_message_size(attach_handle, &link_instance->peer_max_message_size) != 0) |
AzureIoTClient | 28:add19eb7defa | 340 | { |
AzureIoTClient | 28:add19eb7defa | 341 | LogError("Could not retrieve peer_max_message_size from attach frame"); |
AzureIoTClient | 28:add19eb7defa | 342 | } |
AzureIoTClient | 24:2c59c2d43ebf | 343 | |
AzureIoTClient | 28:add19eb7defa | 344 | if ((link_instance->link_state == LINK_STATE_DETACHED) || |
AzureIoTClient | 28:add19eb7defa | 345 | (link_instance->link_state == LINK_STATE_HALF_ATTACHED_ATTACH_SENT)) |
AzureIoTClient | 28:add19eb7defa | 346 | { |
AzureIoTClient | 28:add19eb7defa | 347 | if (link_instance->role == role_receiver) |
AzureIoTClient | 28:add19eb7defa | 348 | { |
AzureIoTClient | 41:0e723f9cbd89 | 349 | link_instance->current_link_credit = link_instance->max_link_credit; |
AzureIoTClient | 28:add19eb7defa | 350 | send_flow(link_instance); |
AzureIoTClient | 28:add19eb7defa | 351 | } |
AzureIoTClient | 28:add19eb7defa | 352 | else |
AzureIoTClient | 28:add19eb7defa | 353 | { |
AzureIoTClient | 41:0e723f9cbd89 | 354 | link_instance->current_link_credit = 0; |
AzureIoTClient | 28:add19eb7defa | 355 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 356 | |
AzureIoTClient | 28:add19eb7defa | 357 | if (link_instance->link_state == LINK_STATE_DETACHED) |
AzureIoTClient | 28:add19eb7defa | 358 | { |
AzureIoTClient | 28:add19eb7defa | 359 | set_link_state(link_instance, LINK_STATE_HALF_ATTACHED_ATTACH_RECEIVED); |
AzureIoTClient | 28:add19eb7defa | 360 | } |
AzureIoTClient | 28:add19eb7defa | 361 | else |
AzureIoTClient | 28:add19eb7defa | 362 | { |
AzureIoTClient | 28:add19eb7defa | 363 | set_link_state(link_instance, LINK_STATE_ATTACHED); |
AzureIoTClient | 28:add19eb7defa | 364 | } |
AzureIoTClient | 28:add19eb7defa | 365 | } |
AzureIoTClient | 28:add19eb7defa | 366 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 367 | |
AzureIoTClient | 28:add19eb7defa | 368 | attach_destroy(attach_handle); |
AzureIoTClient | 28:add19eb7defa | 369 | } |
AzureIoTClient | 28:add19eb7defa | 370 | } |
AzureIoTClient | 28:add19eb7defa | 371 | else if (is_flow_type_by_descriptor(descriptor)) |
AzureIoTClient | 28:add19eb7defa | 372 | { |
AzureIoTClient | 28:add19eb7defa | 373 | FLOW_HANDLE flow_handle; |
AzureIoTClient | 41:0e723f9cbd89 | 374 | if (amqpvalue_get_flow(performative, &flow_handle) != 0) |
AzureIoTClient | 41:0e723f9cbd89 | 375 | { |
AzureIoTClient | 41:0e723f9cbd89 | 376 | LogError("Cannot get flow performative"); |
AzureIoTClient | 41:0e723f9cbd89 | 377 | } |
AzureIoTClient | 41:0e723f9cbd89 | 378 | else |
AzureIoTClient | 28:add19eb7defa | 379 | { |
AzureIoTClient | 28:add19eb7defa | 380 | if (link_instance->role == role_sender) |
AzureIoTClient | 28:add19eb7defa | 381 | { |
AzureIoTClient | 28:add19eb7defa | 382 | delivery_number rcv_delivery_count; |
AzureIoTClient | 28:add19eb7defa | 383 | uint32_t rcv_link_credit; |
Azure.IoT Build | 0:6ae2f7bca550 | 384 | |
AzureIoTClient | 41:0e723f9cbd89 | 385 | if (flow_get_link_credit(flow_handle, &rcv_link_credit) != 0) |
AzureIoTClient | 28:add19eb7defa | 386 | { |
AzureIoTClient | 41:0e723f9cbd89 | 387 | LogError("Cannot get link credit"); |
AzureIoTClient | 41:0e723f9cbd89 | 388 | remove_all_pending_deliveries(link_instance, true); |
AzureIoTClient | 41:0e723f9cbd89 | 389 | set_link_state(link_instance, LINK_STATE_DETACHED); |
AzureIoTClient | 41:0e723f9cbd89 | 390 | } |
AzureIoTClient | 41:0e723f9cbd89 | 391 | else if (flow_get_delivery_count(flow_handle, &rcv_delivery_count) != 0) |
AzureIoTClient | 41:0e723f9cbd89 | 392 | { |
AzureIoTClient | 41:0e723f9cbd89 | 393 | LogError("Cannot get delivery count"); |
AzureIoTClient | 29:4a11413cf217 | 394 | remove_all_pending_deliveries(link_instance, true); |
AzureIoTClient | 28:add19eb7defa | 395 | set_link_state(link_instance, LINK_STATE_DETACHED); |
AzureIoTClient | 28:add19eb7defa | 396 | } |
AzureIoTClient | 28:add19eb7defa | 397 | else |
AzureIoTClient | 28:add19eb7defa | 398 | { |
AzureIoTClient | 41:0e723f9cbd89 | 399 | link_instance->current_link_credit = rcv_delivery_count + rcv_link_credit - link_instance->delivery_count; |
AzureIoTClient | 41:0e723f9cbd89 | 400 | if (link_instance->current_link_credit > 0) |
AzureIoTClient | 28:add19eb7defa | 401 | { |
AzureIoTClient | 28:add19eb7defa | 402 | link_instance->on_link_flow_on(link_instance->callback_context); |
AzureIoTClient | 28:add19eb7defa | 403 | } |
AzureIoTClient | 28:add19eb7defa | 404 | } |
AzureIoTClient | 28:add19eb7defa | 405 | } |
AzureIoTClient | 28:add19eb7defa | 406 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 407 | |
AzureIoTClient | 28:add19eb7defa | 408 | flow_destroy(flow_handle); |
AzureIoTClient | 28:add19eb7defa | 409 | } |
AzureIoTClient | 28:add19eb7defa | 410 | else if (is_transfer_type_by_descriptor(descriptor)) |
AzureIoTClient | 28:add19eb7defa | 411 | { |
AzureIoTClient | 28:add19eb7defa | 412 | if (link_instance->on_transfer_received != NULL) |
AzureIoTClient | 28:add19eb7defa | 413 | { |
AzureIoTClient | 28:add19eb7defa | 414 | TRANSFER_HANDLE transfer_handle; |
AzureIoTClient | 41:0e723f9cbd89 | 415 | if (amqpvalue_get_transfer(performative, &transfer_handle) != 0) |
AzureIoTClient | 41:0e723f9cbd89 | 416 | { |
AzureIoTClient | 41:0e723f9cbd89 | 417 | LogError("Cannot get transfer performative"); |
AzureIoTClient | 41:0e723f9cbd89 | 418 | } |
AzureIoTClient | 41:0e723f9cbd89 | 419 | else |
AzureIoTClient | 28:add19eb7defa | 420 | { |
AzureIoTClient | 28:add19eb7defa | 421 | AMQP_VALUE delivery_state; |
AzureIoTClient | 12:b30dacf113f2 | 422 | bool more; |
AzureIoTClient | 28:add19eb7defa | 423 | bool is_error; |
Azure.IoT Build | 0:6ae2f7bca550 | 424 | |
AzureIoTClient | 41:0e723f9cbd89 | 425 | link_instance->current_link_credit--; |
AzureIoTClient | 28:add19eb7defa | 426 | link_instance->delivery_count++; |
AzureIoTClient | 41:0e723f9cbd89 | 427 | if (link_instance->current_link_credit == 0) |
AzureIoTClient | 28:add19eb7defa | 428 | { |
AzureIoTClient | 41:0e723f9cbd89 | 429 | link_instance->current_link_credit = link_instance->max_link_credit; |
AzureIoTClient | 28:add19eb7defa | 430 | send_flow(link_instance); |
AzureIoTClient | 28:add19eb7defa | 431 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 432 | |
AzureIoTClient | 28:add19eb7defa | 433 | more = false; |
AzureIoTClient | 28:add19eb7defa | 434 | /* Attempt to get more flag, default to false */ |
AzureIoTClient | 28:add19eb7defa | 435 | (void)transfer_get_more(transfer_handle, &more); |
AzureIoTClient | 28:add19eb7defa | 436 | is_error = false; |
AzureIoTClient | 12:b30dacf113f2 | 437 | |
AzureIoTClient | 13:9abd748f4e78 | 438 | if (transfer_get_delivery_id(transfer_handle, &link_instance->received_delivery_id) != 0) |
AzureIoTClient | 13:9abd748f4e78 | 439 | { |
AzureIoTClient | 13:9abd748f4e78 | 440 | /* is this not a continuation transfer? */ |
AzureIoTClient | 13:9abd748f4e78 | 441 | if (link_instance->received_payload_size == 0) |
AzureIoTClient | 12:b30dacf113f2 | 442 | { |
AzureIoTClient | 13:9abd748f4e78 | 443 | LogError("Could not get the delivery Id from the transfer performative"); |
AzureIoTClient | 13:9abd748f4e78 | 444 | is_error = true; |
AzureIoTClient | 13:9abd748f4e78 | 445 | } |
AzureIoTClient | 13:9abd748f4e78 | 446 | } |
AzureIoTClient | 46:01f7ca900e07 | 447 | |
AzureIoTClient | 13:9abd748f4e78 | 448 | if (!is_error) |
AzureIoTClient | 13:9abd748f4e78 | 449 | { |
AzureIoTClient | 13:9abd748f4e78 | 450 | /* If this is a continuation transfer or if this is the first chunk of a multi frame transfer */ |
AzureIoTClient | 13:9abd748f4e78 | 451 | if ((link_instance->received_payload_size > 0) || more) |
AzureIoTClient | 13:9abd748f4e78 | 452 | { |
AzureIoTClient | 13:9abd748f4e78 | 453 | unsigned char* new_received_payload = (unsigned char*)realloc(link_instance->received_payload, link_instance->received_payload_size + payload_size); |
AzureIoTClient | 13:9abd748f4e78 | 454 | if (new_received_payload == NULL) |
AzureIoTClient | 12:b30dacf113f2 | 455 | { |
AzureIoTClient | 13:9abd748f4e78 | 456 | LogError("Could not allocate memory for the received payload"); |
AzureIoTClient | 13:9abd748f4e78 | 457 | } |
AzureIoTClient | 13:9abd748f4e78 | 458 | else |
AzureIoTClient | 13:9abd748f4e78 | 459 | { |
AzureIoTClient | 13:9abd748f4e78 | 460 | link_instance->received_payload = new_received_payload; |
AzureIoTClient | 13:9abd748f4e78 | 461 | (void)memcpy(link_instance->received_payload + link_instance->received_payload_size, payload_bytes, payload_size); |
AzureIoTClient | 13:9abd748f4e78 | 462 | link_instance->received_payload_size += payload_size; |
AzureIoTClient | 12:b30dacf113f2 | 463 | } |
AzureIoTClient | 12:b30dacf113f2 | 464 | } |
AzureIoTClient | 13:9abd748f4e78 | 465 | |
AzureIoTClient | 13:9abd748f4e78 | 466 | if (!more) |
AzureIoTClient | 12:b30dacf113f2 | 467 | { |
AzureIoTClient | 13:9abd748f4e78 | 468 | const unsigned char* indicate_payload_bytes; |
AzureIoTClient | 13:9abd748f4e78 | 469 | uint32_t indicate_payload_size; |
AzureIoTClient | 13:9abd748f4e78 | 470 | |
AzureIoTClient | 13:9abd748f4e78 | 471 | /* if no previously stored chunks then simply report the current payload */ |
AzureIoTClient | 13:9abd748f4e78 | 472 | if (link_instance->received_payload_size > 0) |
AzureIoTClient | 12:b30dacf113f2 | 473 | { |
AzureIoTClient | 13:9abd748f4e78 | 474 | indicate_payload_size = link_instance->received_payload_size; |
AzureIoTClient | 13:9abd748f4e78 | 475 | indicate_payload_bytes = link_instance->received_payload; |
AzureIoTClient | 13:9abd748f4e78 | 476 | } |
AzureIoTClient | 13:9abd748f4e78 | 477 | else |
AzureIoTClient | 13:9abd748f4e78 | 478 | { |
AzureIoTClient | 13:9abd748f4e78 | 479 | indicate_payload_size = payload_size; |
AzureIoTClient | 13:9abd748f4e78 | 480 | indicate_payload_bytes = payload_bytes; |
AzureIoTClient | 12:b30dacf113f2 | 481 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 482 | |
AzureIoTClient | 13:9abd748f4e78 | 483 | delivery_state = link_instance->on_transfer_received(link_instance->callback_context, transfer_handle, indicate_payload_size, indicate_payload_bytes); |
AzureIoTClient | 12:b30dacf113f2 | 484 | |
AzureIoTClient | 13:9abd748f4e78 | 485 | if (link_instance->received_payload_size > 0) |
AzureIoTClient | 13:9abd748f4e78 | 486 | { |
AzureIoTClient | 13:9abd748f4e78 | 487 | free(link_instance->received_payload); |
AzureIoTClient | 13:9abd748f4e78 | 488 | link_instance->received_payload = NULL; |
AzureIoTClient | 13:9abd748f4e78 | 489 | link_instance->received_payload_size = 0; |
AzureIoTClient | 13:9abd748f4e78 | 490 | } |
AzureIoTClient | 12:b30dacf113f2 | 491 | |
AzureIoTClient | 13:9abd748f4e78 | 492 | if (delivery_state != NULL) |
AzureIoTClient | 13:9abd748f4e78 | 493 | { |
AzureIoTClient | 20:206846c14c80 | 494 | if (send_disposition(link_instance, link_instance->received_delivery_id, delivery_state) != 0) |
AzureIoTClient | 20:206846c14c80 | 495 | { |
AzureIoTClient | 20:206846c14c80 | 496 | LogError("Cannot send disposition frame"); |
AzureIoTClient | 20:206846c14c80 | 497 | } |
AzureIoTClient | 41:0e723f9cbd89 | 498 | |
AzureIoTClient | 13:9abd748f4e78 | 499 | amqpvalue_destroy(delivery_state); |
AzureIoTClient | 12:b30dacf113f2 | 500 | } |
AzureIoTClient | 12:b30dacf113f2 | 501 | } |
AzureIoTClient | 12:b30dacf113f2 | 502 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 503 | |
AzureIoTClient | 28:add19eb7defa | 504 | transfer_destroy(transfer_handle); |
AzureIoTClient | 28:add19eb7defa | 505 | } |
AzureIoTClient | 28:add19eb7defa | 506 | } |
AzureIoTClient | 28:add19eb7defa | 507 | } |
AzureIoTClient | 28:add19eb7defa | 508 | else if (is_disposition_type_by_descriptor(descriptor)) |
AzureIoTClient | 28:add19eb7defa | 509 | { |
AzureIoTClient | 28:add19eb7defa | 510 | DISPOSITION_HANDLE disposition; |
AzureIoTClient | 28:add19eb7defa | 511 | if (amqpvalue_get_disposition(performative, &disposition) != 0) |
AzureIoTClient | 28:add19eb7defa | 512 | { |
AzureIoTClient | 41:0e723f9cbd89 | 513 | LogError("Cannot get disposition performative"); |
AzureIoTClient | 28:add19eb7defa | 514 | } |
AzureIoTClient | 28:add19eb7defa | 515 | else |
AzureIoTClient | 28:add19eb7defa | 516 | { |
AzureIoTClient | 28:add19eb7defa | 517 | delivery_number first; |
AzureIoTClient | 28:add19eb7defa | 518 | delivery_number last; |
Azure.IoT Build | 0:6ae2f7bca550 | 519 | |
AzureIoTClient | 28:add19eb7defa | 520 | if (disposition_get_first(disposition, &first) != 0) |
AzureIoTClient | 28:add19eb7defa | 521 | { |
AzureIoTClient | 41:0e723f9cbd89 | 522 | LogError("Cannot get first field"); |
AzureIoTClient | 28:add19eb7defa | 523 | } |
AzureIoTClient | 28:add19eb7defa | 524 | else |
AzureIoTClient | 28:add19eb7defa | 525 | { |
Azure.IoT Build | 0:6ae2f7bca550 | 526 | bool settled; |
Azure.IoT Build | 0:6ae2f7bca550 | 527 | |
AzureIoTClient | 28:add19eb7defa | 528 | if (disposition_get_last(disposition, &last) != 0) |
AzureIoTClient | 28:add19eb7defa | 529 | { |
AzureIoTClient | 28:add19eb7defa | 530 | last = first; |
AzureIoTClient | 28:add19eb7defa | 531 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 532 | |
Azure.IoT Build | 0:6ae2f7bca550 | 533 | if (disposition_get_settled(disposition, &settled) != 0) |
Azure.IoT Build | 0:6ae2f7bca550 | 534 | { |
Azure.IoT Build | 0:6ae2f7bca550 | 535 | settled = false; |
Azure.IoT Build | 0:6ae2f7bca550 | 536 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 537 | |
Azure.IoT Build | 0:6ae2f7bca550 | 538 | if (settled) |
Azure.IoT Build | 0:6ae2f7bca550 | 539 | { |
AzureIoTClient | 12:b30dacf113f2 | 540 | LIST_ITEM_HANDLE pending_delivery = singlylinkedlist_get_head_item(link_instance->pending_deliveries); |
Azure.IoT Build | 0:6ae2f7bca550 | 541 | while (pending_delivery != NULL) |
Azure.IoT Build | 0:6ae2f7bca550 | 542 | { |
AzureIoTClient | 12:b30dacf113f2 | 543 | LIST_ITEM_HANDLE next_pending_delivery = singlylinkedlist_get_next_item(pending_delivery); |
AzureIoTClient | 36:8e1d94b0a70c | 544 | ASYNC_OPERATION_HANDLE pending_delivery_operation = (ASYNC_OPERATION_HANDLE)singlylinkedlist_item_get_value(pending_delivery); |
AzureIoTClient | 36:8e1d94b0a70c | 545 | if (pending_delivery_operation == NULL) |
Azure.IoT Build | 0:6ae2f7bca550 | 546 | { |
AzureIoTClient | 41:0e723f9cbd89 | 547 | LogError("Cannot obtain pending delivery"); |
Azure.IoT Build | 0:6ae2f7bca550 | 548 | break; |
Azure.IoT Build | 0:6ae2f7bca550 | 549 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 550 | else |
Azure.IoT Build | 0:6ae2f7bca550 | 551 | { |
AzureIoTClient | 36:8e1d94b0a70c | 552 | DELIVERY_INSTANCE* delivery_instance = (DELIVERY_INSTANCE*)GET_ASYNC_OPERATION_CONTEXT(DELIVERY_INSTANCE, pending_delivery_operation); |
AzureIoTClient | 36:8e1d94b0a70c | 553 | |
Azure.IoT Build | 0:6ae2f7bca550 | 554 | if ((delivery_instance->delivery_id >= first) && (delivery_instance->delivery_id <= last)) |
Azure.IoT Build | 0:6ae2f7bca550 | 555 | { |
AzureIoTClient | 7:9e9ab3b0efef | 556 | AMQP_VALUE delivery_state; |
AzureIoTClient | 41:0e723f9cbd89 | 557 | if (disposition_get_state(disposition, &delivery_state) == 0) |
Azure.IoT Build | 0:6ae2f7bca550 | 558 | { |
AzureIoTClient | 23:1111ee8bcba4 | 559 | delivery_instance->on_delivery_settled(delivery_instance->callback_context, delivery_instance->delivery_id, LINK_DELIVERY_SETTLE_REASON_DISPOSITION_RECEIVED, delivery_state); |
AzureIoTClient | 36:8e1d94b0a70c | 560 | async_operation_destroy(pending_delivery_operation); |
AzureIoTClient | 12:b30dacf113f2 | 561 | if (singlylinkedlist_remove(link_instance->pending_deliveries, pending_delivery) != 0) |
AzureIoTClient | 7:9e9ab3b0efef | 562 | { |
AzureIoTClient | 41:0e723f9cbd89 | 563 | LogError("Cannot remove pending delivery"); |
AzureIoTClient | 7:9e9ab3b0efef | 564 | break; |
AzureIoTClient | 7:9e9ab3b0efef | 565 | } |
AzureIoTClient | 41:0e723f9cbd89 | 566 | |
AzureIoTClient | 41:0e723f9cbd89 | 567 | pending_delivery = next_pending_delivery; |
Azure.IoT Build | 0:6ae2f7bca550 | 568 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 569 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 570 | else |
Azure.IoT Build | 0:6ae2f7bca550 | 571 | { |
Azure.IoT Build | 0:6ae2f7bca550 | 572 | pending_delivery = next_pending_delivery; |
Azure.IoT Build | 0:6ae2f7bca550 | 573 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 574 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 575 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 576 | } |
AzureIoTClient | 28:add19eb7defa | 577 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 578 | |
AzureIoTClient | 28:add19eb7defa | 579 | disposition_destroy(disposition); |
AzureIoTClient | 28:add19eb7defa | 580 | } |
AzureIoTClient | 28:add19eb7defa | 581 | } |
AzureIoTClient | 28:add19eb7defa | 582 | else if (is_detach_type_by_descriptor(descriptor)) |
AzureIoTClient | 28:add19eb7defa | 583 | { |
AzureIoTClient | 1:eab586236bfe | 584 | DETACH_HANDLE detach; |
AzureIoTClient | 1:eab586236bfe | 585 | |
AzureIoTClient | 1:eab586236bfe | 586 | /* Set link state appropriately based on whether we received detach condition */ |
AzureIoTClient | 41:0e723f9cbd89 | 587 | if (amqpvalue_get_detach(performative, &detach) != 0) |
AzureIoTClient | 41:0e723f9cbd89 | 588 | { |
AzureIoTClient | 41:0e723f9cbd89 | 589 | LogError("Cannot get detach performative"); |
AzureIoTClient | 41:0e723f9cbd89 | 590 | } |
AzureIoTClient | 41:0e723f9cbd89 | 591 | else |
AzureIoTClient | 1:eab586236bfe | 592 | { |
AzureIoTClient | 12:b30dacf113f2 | 593 | bool closed = false; |
AzureIoTClient | 1:eab586236bfe | 594 | ERROR_HANDLE error; |
AzureIoTClient | 19:000ab4e6a2c1 | 595 | |
AzureIoTClient | 44:9dd558f13109 | 596 | (void)detach_get_closed(detach, &closed); |
AzureIoTClient | 44:9dd558f13109 | 597 | |
AzureIoTClient | 19:000ab4e6a2c1 | 598 | /* Received a detach while attached */ |
AzureIoTClient | 19:000ab4e6a2c1 | 599 | if (link_instance->link_state == LINK_STATE_ATTACHED) |
AzureIoTClient | 19:000ab4e6a2c1 | 600 | { |
AzureIoTClient | 19:000ab4e6a2c1 | 601 | /* Respond with ack */ |
AzureIoTClient | 41:0e723f9cbd89 | 602 | if (send_detach(link_instance, closed, NULL) != 0) |
AzureIoTClient | 41:0e723f9cbd89 | 603 | { |
AzureIoTClient | 41:0e723f9cbd89 | 604 | LogError("Failed sending detach frame"); |
AzureIoTClient | 41:0e723f9cbd89 | 605 | } |
AzureIoTClient | 19:000ab4e6a2c1 | 606 | } |
AzureIoTClient | 19:000ab4e6a2c1 | 607 | /* Received a closing detach after we sent a non-closing detach. */ |
AzureIoTClient | 19:000ab4e6a2c1 | 608 | else if (closed && |
AzureIoTClient | 24:2c59c2d43ebf | 609 | ((link_instance->link_state == LINK_STATE_HALF_ATTACHED_ATTACH_SENT) || (link_instance->link_state == LINK_STATE_HALF_ATTACHED_ATTACH_RECEIVED)) && |
AzureIoTClient | 19:000ab4e6a2c1 | 610 | !link_instance->is_closed) |
AzureIoTClient | 19:000ab4e6a2c1 | 611 | { |
AzureIoTClient | 19:000ab4e6a2c1 | 612 | |
AzureIoTClient | 19:000ab4e6a2c1 | 613 | /* In this case, we MUST signal that we closed by reattaching and then sending a closing detach.*/ |
AzureIoTClient | 41:0e723f9cbd89 | 614 | if (send_attach(link_instance, link_instance->name, 0, link_instance->role) != 0) |
AzureIoTClient | 41:0e723f9cbd89 | 615 | { |
AzureIoTClient | 41:0e723f9cbd89 | 616 | LogError("Failed sending attach frame"); |
AzureIoTClient | 41:0e723f9cbd89 | 617 | } |
AzureIoTClient | 41:0e723f9cbd89 | 618 | |
AzureIoTClient | 41:0e723f9cbd89 | 619 | if (send_detach(link_instance, true, NULL) != 0) |
AzureIoTClient | 41:0e723f9cbd89 | 620 | { |
AzureIoTClient | 41:0e723f9cbd89 | 621 | LogError("Failed sending detach frame"); |
AzureIoTClient | 41:0e723f9cbd89 | 622 | } |
AzureIoTClient | 19:000ab4e6a2c1 | 623 | } |
AzureIoTClient | 19:000ab4e6a2c1 | 624 | |
AzureIoTClient | 46:01f7ca900e07 | 625 | if (detach_get_error(detach, &error) != 0) |
AzureIoTClient | 1:eab586236bfe | 626 | { |
AzureIoTClient | 46:01f7ca900e07 | 627 | error = NULL; |
AzureIoTClient | 46:01f7ca900e07 | 628 | } |
AzureIoTClient | 46:01f7ca900e07 | 629 | remove_all_pending_deliveries(link_instance, true); |
AzureIoTClient | 46:01f7ca900e07 | 630 | // signal link detach received in order to handle cases like redirect |
AzureIoTClient | 46:01f7ca900e07 | 631 | if (link_instance->on_link_detach_received_event_subscription.on_link_detach_received != NULL) |
AzureIoTClient | 46:01f7ca900e07 | 632 | { |
AzureIoTClient | 46:01f7ca900e07 | 633 | link_instance->on_link_detach_received_event_subscription.on_link_detach_received(link_instance->on_link_detach_received_event_subscription.context, error); |
AzureIoTClient | 46:01f7ca900e07 | 634 | } |
AzureIoTClient | 43:4c1e4e94cdd3 | 635 | |
AzureIoTClient | 46:01f7ca900e07 | 636 | if (error != NULL) |
AzureIoTClient | 46:01f7ca900e07 | 637 | { |
AzureIoTClient | 46:01f7ca900e07 | 638 | set_link_state(link_instance, LINK_STATE_ERROR); |
AzureIoTClient | 43:4c1e4e94cdd3 | 639 | error_destroy(error); |
AzureIoTClient | 1:eab586236bfe | 640 | } |
AzureIoTClient | 46:01f7ca900e07 | 641 | else |
AzureIoTClient | 1:eab586236bfe | 642 | { |
AzureIoTClient | 1:eab586236bfe | 643 | set_link_state(link_instance, LINK_STATE_DETACHED); |
AzureIoTClient | 1:eab586236bfe | 644 | } |
AzureIoTClient | 12:b30dacf113f2 | 645 | |
AzureIoTClient | 12:b30dacf113f2 | 646 | detach_destroy(detach); |
AzureIoTClient | 1:eab586236bfe | 647 | } |
AzureIoTClient | 1:eab586236bfe | 648 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 649 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 650 | |
Azure.IoT Build | 0:6ae2f7bca550 | 651 | static void on_session_state_changed(void* context, SESSION_STATE new_session_state, SESSION_STATE previous_session_state) |
Azure.IoT Build | 0:6ae2f7bca550 | 652 | { |
AzureIoTClient | 28:add19eb7defa | 653 | LINK_INSTANCE* link_instance = (LINK_INSTANCE*)context; |
AzureIoTClient | 6:641a9672db08 | 654 | (void)previous_session_state; |
Azure.IoT Build | 0:6ae2f7bca550 | 655 | |
AzureIoTClient | 28:add19eb7defa | 656 | if (new_session_state == SESSION_STATE_MAPPED) |
AzureIoTClient | 28:add19eb7defa | 657 | { |
AzureIoTClient | 28:add19eb7defa | 658 | if ((link_instance->link_state == LINK_STATE_DETACHED) && (!link_instance->is_closed)) |
AzureIoTClient | 28:add19eb7defa | 659 | { |
AzureIoTClient | 28:add19eb7defa | 660 | if (send_attach(link_instance, link_instance->name, 0, link_instance->role) == 0) |
AzureIoTClient | 28:add19eb7defa | 661 | { |
AzureIoTClient | 28:add19eb7defa | 662 | set_link_state(link_instance, LINK_STATE_HALF_ATTACHED_ATTACH_SENT); |
AzureIoTClient | 28:add19eb7defa | 663 | } |
AzureIoTClient | 28:add19eb7defa | 664 | } |
AzureIoTClient | 28:add19eb7defa | 665 | } |
AzureIoTClient | 28:add19eb7defa | 666 | else if (new_session_state == SESSION_STATE_DISCARDING) |
AzureIoTClient | 28:add19eb7defa | 667 | { |
AzureIoTClient | 36:8e1d94b0a70c | 668 | remove_all_pending_deliveries(link_instance, true); |
AzureIoTClient | 36:8e1d94b0a70c | 669 | set_link_state(link_instance, LINK_STATE_DETACHED); |
AzureIoTClient | 28:add19eb7defa | 670 | } |
AzureIoTClient | 28:add19eb7defa | 671 | else if (new_session_state == SESSION_STATE_ERROR) |
AzureIoTClient | 28:add19eb7defa | 672 | { |
AzureIoTClient | 36:8e1d94b0a70c | 673 | remove_all_pending_deliveries(link_instance, true); |
AzureIoTClient | 36:8e1d94b0a70c | 674 | set_link_state(link_instance, LINK_STATE_ERROR); |
AzureIoTClient | 28:add19eb7defa | 675 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 676 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 677 | |
Azure.IoT Build | 0:6ae2f7bca550 | 678 | static void on_session_flow_on(void* context) |
Azure.IoT Build | 0:6ae2f7bca550 | 679 | { |
AzureIoTClient | 28:add19eb7defa | 680 | LINK_INSTANCE* link_instance = (LINK_INSTANCE*)context; |
AzureIoTClient | 28:add19eb7defa | 681 | if (link_instance->role == role_sender) |
AzureIoTClient | 28:add19eb7defa | 682 | { |
AzureIoTClient | 28:add19eb7defa | 683 | link_instance->on_link_flow_on(link_instance->callback_context); |
AzureIoTClient | 28:add19eb7defa | 684 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 685 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 686 | |
Azure.IoT Build | 0:6ae2f7bca550 | 687 | static void on_send_complete(void* context, IO_SEND_RESULT send_result) |
Azure.IoT Build | 0:6ae2f7bca550 | 688 | { |
AzureIoTClient | 28:add19eb7defa | 689 | LIST_ITEM_HANDLE delivery_instance_list_item = (LIST_ITEM_HANDLE)context; |
AzureIoTClient | 36:8e1d94b0a70c | 690 | ASYNC_OPERATION_HANDLE pending_delivery_operation = (ASYNC_OPERATION_HANDLE)singlylinkedlist_item_get_value(delivery_instance_list_item); |
AzureIoTClient | 36:8e1d94b0a70c | 691 | DELIVERY_INSTANCE* delivery_instance = (DELIVERY_INSTANCE*)GET_ASYNC_OPERATION_CONTEXT(DELIVERY_INSTANCE, pending_delivery_operation); |
AzureIoTClient | 36:8e1d94b0a70c | 692 | LINK_HANDLE link = (LINK_HANDLE)delivery_instance->link; |
AzureIoTClient | 6:641a9672db08 | 693 | (void)send_result; |
AzureIoTClient | 36:8e1d94b0a70c | 694 | if (link->snd_settle_mode == sender_settle_mode_settled) |
AzureIoTClient | 28:add19eb7defa | 695 | { |
AzureIoTClient | 28:add19eb7defa | 696 | delivery_instance->on_delivery_settled(delivery_instance->callback_context, delivery_instance->delivery_id, LINK_DELIVERY_SETTLE_REASON_SETTLED, NULL); |
AzureIoTClient | 36:8e1d94b0a70c | 697 | async_operation_destroy(pending_delivery_operation); |
AzureIoTClient | 36:8e1d94b0a70c | 698 | (void)singlylinkedlist_remove(link->pending_deliveries, delivery_instance_list_item); |
AzureIoTClient | 28:add19eb7defa | 699 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 700 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 701 | |
Azure.IoT Build | 0:6ae2f7bca550 | 702 | LINK_HANDLE link_create(SESSION_HANDLE session, const char* name, role role, AMQP_VALUE source, AMQP_VALUE target) |
Azure.IoT Build | 0:6ae2f7bca550 | 703 | { |
AzureIoTClient | 28:add19eb7defa | 704 | LINK_INSTANCE* result = (LINK_INSTANCE*)malloc(sizeof(LINK_INSTANCE)); |
AzureIoTClient | 41:0e723f9cbd89 | 705 | if (result == NULL) |
AzureIoTClient | 41:0e723f9cbd89 | 706 | { |
AzureIoTClient | 41:0e723f9cbd89 | 707 | LogError("Cannot create link"); |
AzureIoTClient | 41:0e723f9cbd89 | 708 | } |
AzureIoTClient | 41:0e723f9cbd89 | 709 | else |
AzureIoTClient | 28:add19eb7defa | 710 | { |
AzureIoTClient | 28:add19eb7defa | 711 | result->link_state = LINK_STATE_DETACHED; |
AzureIoTClient | 28:add19eb7defa | 712 | result->previous_link_state = LINK_STATE_DETACHED; |
AzureIoTClient | 28:add19eb7defa | 713 | result->role = role; |
AzureIoTClient | 28:add19eb7defa | 714 | result->source = amqpvalue_clone(source); |
AzureIoTClient | 28:add19eb7defa | 715 | result->target = amqpvalue_clone(target); |
AzureIoTClient | 28:add19eb7defa | 716 | result->session = session; |
AzureIoTClient | 28:add19eb7defa | 717 | result->handle = 0; |
AzureIoTClient | 28:add19eb7defa | 718 | result->snd_settle_mode = sender_settle_mode_unsettled; |
AzureIoTClient | 28:add19eb7defa | 719 | result->rcv_settle_mode = receiver_settle_mode_first; |
AzureIoTClient | 28:add19eb7defa | 720 | result->delivery_count = 0; |
AzureIoTClient | 28:add19eb7defa | 721 | result->initial_delivery_count = 0; |
AzureIoTClient | 28:add19eb7defa | 722 | result->max_message_size = 0; |
AzureIoTClient | 41:0e723f9cbd89 | 723 | result->max_link_credit = DEFAULT_LINK_CREDIT; |
AzureIoTClient | 28:add19eb7defa | 724 | result->peer_max_message_size = 0; |
AzureIoTClient | 28:add19eb7defa | 725 | result->is_underlying_session_begun = false; |
AzureIoTClient | 12:b30dacf113f2 | 726 | result->is_closed = false; |
Azure.IoT Build | 0:6ae2f7bca550 | 727 | result->attach_properties = NULL; |
AzureIoTClient | 12:b30dacf113f2 | 728 | result->received_payload = NULL; |
AzureIoTClient | 12:b30dacf113f2 | 729 | result->received_payload_size = 0; |
AzureIoTClient | 12:b30dacf113f2 | 730 | result->received_delivery_id = 0; |
AzureIoTClient | 43:4c1e4e94cdd3 | 731 | result->on_link_detach_received_event_subscription.on_link_detach_received = NULL; |
AzureIoTClient | 43:4c1e4e94cdd3 | 732 | result->on_link_detach_received_event_subscription.context = NULL; |
Azure.IoT Build | 0:6ae2f7bca550 | 733 | |
AzureIoTClient | 34:6be9c2058664 | 734 | result->tick_counter = tickcounter_create(); |
AzureIoTClient | 34:6be9c2058664 | 735 | if (result->tick_counter == NULL) |
AzureIoTClient | 28:add19eb7defa | 736 | { |
AzureIoTClient | 41:0e723f9cbd89 | 737 | LogError("Cannot create tick counter for link"); |
AzureIoTClient | 28:add19eb7defa | 738 | free(result); |
AzureIoTClient | 28:add19eb7defa | 739 | result = NULL; |
AzureIoTClient | 28:add19eb7defa | 740 | } |
AzureIoTClient | 28:add19eb7defa | 741 | else |
AzureIoTClient | 28:add19eb7defa | 742 | { |
AzureIoTClient | 34:6be9c2058664 | 743 | result->pending_deliveries = singlylinkedlist_create(); |
AzureIoTClient | 34:6be9c2058664 | 744 | if (result->pending_deliveries == NULL) |
AzureIoTClient | 28:add19eb7defa | 745 | { |
AzureIoTClient | 41:0e723f9cbd89 | 746 | LogError("Cannot create pending deliveries list"); |
AzureIoTClient | 34:6be9c2058664 | 747 | tickcounter_destroy(result->tick_counter); |
AzureIoTClient | 28:add19eb7defa | 748 | free(result); |
AzureIoTClient | 28:add19eb7defa | 749 | result = NULL; |
AzureIoTClient | 28:add19eb7defa | 750 | } |
AzureIoTClient | 28:add19eb7defa | 751 | else |
AzureIoTClient | 28:add19eb7defa | 752 | { |
AzureIoTClient | 34:6be9c2058664 | 753 | size_t name_length = strlen(name); |
AzureIoTClient | 34:6be9c2058664 | 754 | result->name = (char*)malloc(name_length + 1); |
AzureIoTClient | 34:6be9c2058664 | 755 | if (result->name == NULL) |
AzureIoTClient | 28:add19eb7defa | 756 | { |
AzureIoTClient | 41:0e723f9cbd89 | 757 | LogError("Cannot allocate memory for link name"); |
AzureIoTClient | 34:6be9c2058664 | 758 | tickcounter_destroy(result->tick_counter); |
AzureIoTClient | 28:add19eb7defa | 759 | singlylinkedlist_destroy(result->pending_deliveries); |
AzureIoTClient | 28:add19eb7defa | 760 | free(result); |
AzureIoTClient | 28:add19eb7defa | 761 | result = NULL; |
AzureIoTClient | 28:add19eb7defa | 762 | } |
AzureIoTClient | 34:6be9c2058664 | 763 | else |
AzureIoTClient | 34:6be9c2058664 | 764 | { |
AzureIoTClient | 34:6be9c2058664 | 765 | result->on_link_state_changed = NULL; |
AzureIoTClient | 34:6be9c2058664 | 766 | result->callback_context = NULL; |
AzureIoTClient | 34:6be9c2058664 | 767 | set_link_state(result, LINK_STATE_DETACHED); |
AzureIoTClient | 34:6be9c2058664 | 768 | |
AzureIoTClient | 34:6be9c2058664 | 769 | (void)memcpy(result->name, name, name_length + 1); |
AzureIoTClient | 34:6be9c2058664 | 770 | result->link_endpoint = session_create_link_endpoint(session, name); |
AzureIoTClient | 34:6be9c2058664 | 771 | if (result->link_endpoint == NULL) |
AzureIoTClient | 34:6be9c2058664 | 772 | { |
AzureIoTClient | 41:0e723f9cbd89 | 773 | LogError("Cannot create link endpoint"); |
AzureIoTClient | 34:6be9c2058664 | 774 | tickcounter_destroy(result->tick_counter); |
AzureIoTClient | 34:6be9c2058664 | 775 | singlylinkedlist_destroy(result->pending_deliveries); |
AzureIoTClient | 34:6be9c2058664 | 776 | free(result->name); |
AzureIoTClient | 34:6be9c2058664 | 777 | free(result); |
AzureIoTClient | 34:6be9c2058664 | 778 | result = NULL; |
AzureIoTClient | 34:6be9c2058664 | 779 | } |
AzureIoTClient | 34:6be9c2058664 | 780 | } |
AzureIoTClient | 28:add19eb7defa | 781 | } |
AzureIoTClient | 28:add19eb7defa | 782 | } |
AzureIoTClient | 28:add19eb7defa | 783 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 784 | |
AzureIoTClient | 28:add19eb7defa | 785 | return result; |
Azure.IoT Build | 0:6ae2f7bca550 | 786 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 787 | |
Azure.IoT Build | 0:6ae2f7bca550 | 788 | 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 | 789 | { |
AzureIoTClient | 28:add19eb7defa | 790 | LINK_INSTANCE* result = (LINK_INSTANCE*)malloc(sizeof(LINK_INSTANCE)); |
AzureIoTClient | 41:0e723f9cbd89 | 791 | if (result == NULL) |
AzureIoTClient | 41:0e723f9cbd89 | 792 | { |
AzureIoTClient | 41:0e723f9cbd89 | 793 | LogError("Cannot create link"); |
AzureIoTClient | 41:0e723f9cbd89 | 794 | } |
AzureIoTClient | 41:0e723f9cbd89 | 795 | else |
AzureIoTClient | 28:add19eb7defa | 796 | { |
AzureIoTClient | 28:add19eb7defa | 797 | result->link_state = LINK_STATE_DETACHED; |
AzureIoTClient | 28:add19eb7defa | 798 | result->previous_link_state = LINK_STATE_DETACHED; |
AzureIoTClient | 28:add19eb7defa | 799 | result->session = session; |
AzureIoTClient | 28:add19eb7defa | 800 | result->handle = 0; |
AzureIoTClient | 28:add19eb7defa | 801 | result->snd_settle_mode = sender_settle_mode_unsettled; |
AzureIoTClient | 28:add19eb7defa | 802 | result->rcv_settle_mode = receiver_settle_mode_first; |
AzureIoTClient | 28:add19eb7defa | 803 | result->delivery_count = 0; |
AzureIoTClient | 28:add19eb7defa | 804 | result->initial_delivery_count = 0; |
AzureIoTClient | 28:add19eb7defa | 805 | result->max_message_size = 0; |
AzureIoTClient | 41:0e723f9cbd89 | 806 | result->max_link_credit = DEFAULT_LINK_CREDIT; |
AzureIoTClient | 28:add19eb7defa | 807 | result->peer_max_message_size = 0; |
AzureIoTClient | 28:add19eb7defa | 808 | result->is_underlying_session_begun = false; |
AzureIoTClient | 12:b30dacf113f2 | 809 | result->is_closed = false; |
Azure.IoT Build | 0:6ae2f7bca550 | 810 | result->attach_properties = NULL; |
AzureIoTClient | 12:b30dacf113f2 | 811 | result->received_payload = NULL; |
AzureIoTClient | 12:b30dacf113f2 | 812 | result->received_payload_size = 0; |
AzureIoTClient | 12:b30dacf113f2 | 813 | result->received_delivery_id = 0; |
Azure.IoT Build | 0:6ae2f7bca550 | 814 | result->source = amqpvalue_clone(target); |
AzureIoTClient | 28:add19eb7defa | 815 | result->target = amqpvalue_clone(source); |
AzureIoTClient | 43:4c1e4e94cdd3 | 816 | result->on_link_detach_received_event_subscription.on_link_detach_received = NULL; |
AzureIoTClient | 43:4c1e4e94cdd3 | 817 | result->on_link_detach_received_event_subscription.context = NULL; |
AzureIoTClient | 41:0e723f9cbd89 | 818 | |
AzureIoTClient | 28:add19eb7defa | 819 | if (role == role_sender) |
AzureIoTClient | 28:add19eb7defa | 820 | { |
AzureIoTClient | 28:add19eb7defa | 821 | result->role = role_receiver; |
AzureIoTClient | 28:add19eb7defa | 822 | } |
AzureIoTClient | 28:add19eb7defa | 823 | else |
AzureIoTClient | 28:add19eb7defa | 824 | { |
AzureIoTClient | 28:add19eb7defa | 825 | result->role = role_sender; |
AzureIoTClient | 28:add19eb7defa | 826 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 827 | |
AzureIoTClient | 34:6be9c2058664 | 828 | result->tick_counter = tickcounter_create(); |
AzureIoTClient | 34:6be9c2058664 | 829 | if (result->tick_counter == NULL) |
AzureIoTClient | 28:add19eb7defa | 830 | { |
AzureIoTClient | 41:0e723f9cbd89 | 831 | LogError("Cannot create tick counter for link"); |
AzureIoTClient | 28:add19eb7defa | 832 | free(result); |
AzureIoTClient | 28:add19eb7defa | 833 | result = NULL; |
AzureIoTClient | 28:add19eb7defa | 834 | } |
AzureIoTClient | 28:add19eb7defa | 835 | else |
AzureIoTClient | 28:add19eb7defa | 836 | { |
AzureIoTClient | 34:6be9c2058664 | 837 | result->pending_deliveries = singlylinkedlist_create(); |
AzureIoTClient | 34:6be9c2058664 | 838 | if (result->pending_deliveries == NULL) |
AzureIoTClient | 28:add19eb7defa | 839 | { |
AzureIoTClient | 41:0e723f9cbd89 | 840 | LogError("Cannot create pending deliveries list"); |
AzureIoTClient | 34:6be9c2058664 | 841 | tickcounter_destroy(result->tick_counter); |
AzureIoTClient | 28:add19eb7defa | 842 | free(result); |
AzureIoTClient | 28:add19eb7defa | 843 | result = NULL; |
AzureIoTClient | 28:add19eb7defa | 844 | } |
AzureIoTClient | 28:add19eb7defa | 845 | else |
AzureIoTClient | 28:add19eb7defa | 846 | { |
AzureIoTClient | 34:6be9c2058664 | 847 | size_t name_length = strlen(name); |
AzureIoTClient | 34:6be9c2058664 | 848 | result->name = (char*)malloc(name_length + 1); |
AzureIoTClient | 34:6be9c2058664 | 849 | if (result->name == NULL) |
AzureIoTClient | 34:6be9c2058664 | 850 | { |
AzureIoTClient | 41:0e723f9cbd89 | 851 | LogError("Cannot allocate memory for link name"); |
AzureIoTClient | 34:6be9c2058664 | 852 | tickcounter_destroy(result->tick_counter); |
AzureIoTClient | 34:6be9c2058664 | 853 | singlylinkedlist_destroy(result->pending_deliveries); |
AzureIoTClient | 34:6be9c2058664 | 854 | free(result); |
AzureIoTClient | 34:6be9c2058664 | 855 | result = NULL; |
AzureIoTClient | 34:6be9c2058664 | 856 | } |
AzureIoTClient | 34:6be9c2058664 | 857 | else |
AzureIoTClient | 34:6be9c2058664 | 858 | { |
AzureIoTClient | 34:6be9c2058664 | 859 | (void)memcpy(result->name, name, name_length + 1); |
AzureIoTClient | 34:6be9c2058664 | 860 | result->on_link_state_changed = NULL; |
AzureIoTClient | 34:6be9c2058664 | 861 | result->callback_context = NULL; |
AzureIoTClient | 34:6be9c2058664 | 862 | result->link_endpoint = link_endpoint; |
AzureIoTClient | 34:6be9c2058664 | 863 | } |
AzureIoTClient | 28:add19eb7defa | 864 | } |
AzureIoTClient | 28:add19eb7defa | 865 | } |
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 | void link_destroy(LINK_HANDLE link) |
Azure.IoT Build | 0:6ae2f7bca550 | 872 | { |
AzureIoTClient | 41:0e723f9cbd89 | 873 | if (link == NULL) |
AzureIoTClient | 41:0e723f9cbd89 | 874 | { |
AzureIoTClient | 41:0e723f9cbd89 | 875 | LogError("NULL link"); |
AzureIoTClient | 41:0e723f9cbd89 | 876 | } |
AzureIoTClient | 41:0e723f9cbd89 | 877 | else |
AzureIoTClient | 28:add19eb7defa | 878 | { |
AzureIoTClient | 21:f9c433d8e6ca | 879 | remove_all_pending_deliveries((LINK_INSTANCE*)link, false); |
AzureIoTClient | 34:6be9c2058664 | 880 | tickcounter_destroy(link->tick_counter); |
AzureIoTClient | 21:f9c433d8e6ca | 881 | |
AzureIoTClient | 12:b30dacf113f2 | 882 | link->on_link_state_changed = NULL; |
AzureIoTClient | 43:4c1e4e94cdd3 | 883 | (void)link_detach(link, true, NULL, NULL, NULL); |
AzureIoTClient | 12:b30dacf113f2 | 884 | session_destroy_link_endpoint(link->link_endpoint); |
AzureIoTClient | 28:add19eb7defa | 885 | amqpvalue_destroy(link->source); |
AzureIoTClient | 28:add19eb7defa | 886 | amqpvalue_destroy(link->target); |
Azure.IoT Build | 0:6ae2f7bca550 | 887 | |
AzureIoTClient | 28:add19eb7defa | 888 | if (link->name != NULL) |
AzureIoTClient | 28:add19eb7defa | 889 | { |
AzureIoTClient | 28:add19eb7defa | 890 | free(link->name); |
AzureIoTClient | 28:add19eb7defa | 891 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 892 | |
AzureIoTClient | 28:add19eb7defa | 893 | if (link->attach_properties != NULL) |
Azure.IoT Build | 0:6ae2f7bca550 | 894 | { |
AzureIoTClient | 28:add19eb7defa | 895 | amqpvalue_destroy(link->attach_properties); |
Azure.IoT Build | 0:6ae2f7bca550 | 896 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 897 | |
AzureIoTClient | 12:b30dacf113f2 | 898 | if (link->received_payload != NULL) |
AzureIoTClient | 12:b30dacf113f2 | 899 | { |
AzureIoTClient | 12:b30dacf113f2 | 900 | free(link->received_payload); |
AzureIoTClient | 12:b30dacf113f2 | 901 | } |
AzureIoTClient | 12:b30dacf113f2 | 902 | |
AzureIoTClient | 28:add19eb7defa | 903 | free(link); |
AzureIoTClient | 28:add19eb7defa | 904 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 905 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 906 | |
Azure.IoT Build | 0:6ae2f7bca550 | 907 | int link_set_snd_settle_mode(LINK_HANDLE link, sender_settle_mode snd_settle_mode) |
Azure.IoT Build | 0:6ae2f7bca550 | 908 | { |
AzureIoTClient | 28:add19eb7defa | 909 | int result; |
Azure.IoT Build | 0:6ae2f7bca550 | 910 | |
AzureIoTClient | 28:add19eb7defa | 911 | if (link == NULL) |
AzureIoTClient | 28:add19eb7defa | 912 | { |
AzureIoTClient | 41:0e723f9cbd89 | 913 | LogError("NULL link"); |
AzureIoTClient | 28:add19eb7defa | 914 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 915 | } |
AzureIoTClient | 28:add19eb7defa | 916 | else |
AzureIoTClient | 28:add19eb7defa | 917 | { |
AzureIoTClient | 28:add19eb7defa | 918 | link->snd_settle_mode = snd_settle_mode; |
AzureIoTClient | 28:add19eb7defa | 919 | result = 0; |
AzureIoTClient | 28:add19eb7defa | 920 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 921 | |
AzureIoTClient | 28:add19eb7defa | 922 | return result; |
Azure.IoT Build | 0:6ae2f7bca550 | 923 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 924 | |
Azure.IoT Build | 0:6ae2f7bca550 | 925 | int link_get_snd_settle_mode(LINK_HANDLE link, sender_settle_mode* snd_settle_mode) |
Azure.IoT Build | 0:6ae2f7bca550 | 926 | { |
AzureIoTClient | 28:add19eb7defa | 927 | int result; |
Azure.IoT Build | 0:6ae2f7bca550 | 928 | |
AzureIoTClient | 28:add19eb7defa | 929 | if ((link == NULL) || |
AzureIoTClient | 28:add19eb7defa | 930 | (snd_settle_mode == NULL)) |
AzureIoTClient | 28:add19eb7defa | 931 | { |
AzureIoTClient | 41:0e723f9cbd89 | 932 | LogError("Bad arguments: link = %p, snd_settle_mode = %p", |
AzureIoTClient | 41:0e723f9cbd89 | 933 | link, snd_settle_mode); |
AzureIoTClient | 28:add19eb7defa | 934 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 935 | } |
AzureIoTClient | 28:add19eb7defa | 936 | else |
AzureIoTClient | 28:add19eb7defa | 937 | { |
AzureIoTClient | 28:add19eb7defa | 938 | *snd_settle_mode = link->snd_settle_mode; |
Azure.IoT Build | 0:6ae2f7bca550 | 939 | |
AzureIoTClient | 28:add19eb7defa | 940 | result = 0; |
AzureIoTClient | 28:add19eb7defa | 941 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 942 | |
AzureIoTClient | 28:add19eb7defa | 943 | return result; |
Azure.IoT Build | 0:6ae2f7bca550 | 944 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 945 | |
Azure.IoT Build | 0:6ae2f7bca550 | 946 | int link_set_rcv_settle_mode(LINK_HANDLE link, receiver_settle_mode rcv_settle_mode) |
Azure.IoT Build | 0:6ae2f7bca550 | 947 | { |
AzureIoTClient | 28:add19eb7defa | 948 | int result; |
Azure.IoT Build | 0:6ae2f7bca550 | 949 | |
AzureIoTClient | 28:add19eb7defa | 950 | if (link == NULL) |
AzureIoTClient | 28:add19eb7defa | 951 | { |
AzureIoTClient | 41:0e723f9cbd89 | 952 | LogError("NULL link"); |
AzureIoTClient | 28:add19eb7defa | 953 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 954 | } |
AzureIoTClient | 28:add19eb7defa | 955 | else |
AzureIoTClient | 28:add19eb7defa | 956 | { |
AzureIoTClient | 28:add19eb7defa | 957 | link->rcv_settle_mode = rcv_settle_mode; |
AzureIoTClient | 28:add19eb7defa | 958 | result = 0; |
AzureIoTClient | 28:add19eb7defa | 959 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 960 | |
AzureIoTClient | 28:add19eb7defa | 961 | return result; |
Azure.IoT Build | 0:6ae2f7bca550 | 962 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 963 | |
Azure.IoT Build | 0:6ae2f7bca550 | 964 | int link_get_rcv_settle_mode(LINK_HANDLE link, receiver_settle_mode* rcv_settle_mode) |
Azure.IoT Build | 0:6ae2f7bca550 | 965 | { |
AzureIoTClient | 28:add19eb7defa | 966 | int result; |
Azure.IoT Build | 0:6ae2f7bca550 | 967 | |
AzureIoTClient | 28:add19eb7defa | 968 | if ((link == NULL) || |
AzureIoTClient | 28:add19eb7defa | 969 | (rcv_settle_mode == NULL)) |
AzureIoTClient | 28:add19eb7defa | 970 | { |
AzureIoTClient | 41:0e723f9cbd89 | 971 | LogError("Bad arguments: link = %p, rcv_settle_mode = %p", |
AzureIoTClient | 41:0e723f9cbd89 | 972 | link, rcv_settle_mode); |
AzureIoTClient | 28:add19eb7defa | 973 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 974 | } |
AzureIoTClient | 28:add19eb7defa | 975 | else |
AzureIoTClient | 28:add19eb7defa | 976 | { |
AzureIoTClient | 28:add19eb7defa | 977 | *rcv_settle_mode = link->rcv_settle_mode; |
AzureIoTClient | 28:add19eb7defa | 978 | result = 0; |
AzureIoTClient | 28:add19eb7defa | 979 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 980 | |
AzureIoTClient | 28:add19eb7defa | 981 | return result; |
Azure.IoT Build | 0:6ae2f7bca550 | 982 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 983 | |
Azure.IoT Build | 0:6ae2f7bca550 | 984 | int link_set_initial_delivery_count(LINK_HANDLE link, sequence_no initial_delivery_count) |
Azure.IoT Build | 0:6ae2f7bca550 | 985 | { |
AzureIoTClient | 28:add19eb7defa | 986 | int result; |
Azure.IoT Build | 0:6ae2f7bca550 | 987 | |
AzureIoTClient | 28:add19eb7defa | 988 | if (link == NULL) |
AzureIoTClient | 28:add19eb7defa | 989 | { |
AzureIoTClient | 41:0e723f9cbd89 | 990 | LogError("NULL link"); |
AzureIoTClient | 28:add19eb7defa | 991 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 992 | } |
AzureIoTClient | 28:add19eb7defa | 993 | else |
AzureIoTClient | 28:add19eb7defa | 994 | { |
AzureIoTClient | 28:add19eb7defa | 995 | link->initial_delivery_count = initial_delivery_count; |
AzureIoTClient | 28:add19eb7defa | 996 | result = 0; |
AzureIoTClient | 28:add19eb7defa | 997 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 998 | |
AzureIoTClient | 28:add19eb7defa | 999 | return result; |
Azure.IoT Build | 0:6ae2f7bca550 | 1000 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 1001 | |
Azure.IoT Build | 0:6ae2f7bca550 | 1002 | int link_get_initial_delivery_count(LINK_HANDLE link, sequence_no* initial_delivery_count) |
Azure.IoT Build | 0:6ae2f7bca550 | 1003 | { |
AzureIoTClient | 28:add19eb7defa | 1004 | int result; |
Azure.IoT Build | 0:6ae2f7bca550 | 1005 | |
AzureIoTClient | 28:add19eb7defa | 1006 | if ((link == NULL) || |
AzureIoTClient | 28:add19eb7defa | 1007 | (initial_delivery_count == NULL)) |
AzureIoTClient | 28:add19eb7defa | 1008 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1009 | LogError("Bad arguments: link = %p, initial_delivery_count = %p", |
AzureIoTClient | 41:0e723f9cbd89 | 1010 | link, initial_delivery_count); |
AzureIoTClient | 28:add19eb7defa | 1011 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 1012 | } |
AzureIoTClient | 28:add19eb7defa | 1013 | else |
AzureIoTClient | 28:add19eb7defa | 1014 | { |
AzureIoTClient | 28:add19eb7defa | 1015 | *initial_delivery_count = link->initial_delivery_count; |
AzureIoTClient | 28:add19eb7defa | 1016 | result = 0; |
AzureIoTClient | 28:add19eb7defa | 1017 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 1018 | |
AzureIoTClient | 28:add19eb7defa | 1019 | return result; |
Azure.IoT Build | 0:6ae2f7bca550 | 1020 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 1021 | |
Azure.IoT Build | 0:6ae2f7bca550 | 1022 | int link_set_max_message_size(LINK_HANDLE link, uint64_t max_message_size) |
Azure.IoT Build | 0:6ae2f7bca550 | 1023 | { |
AzureIoTClient | 28:add19eb7defa | 1024 | int result; |
Azure.IoT Build | 0:6ae2f7bca550 | 1025 | |
AzureIoTClient | 28:add19eb7defa | 1026 | if (link == NULL) |
AzureIoTClient | 28:add19eb7defa | 1027 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1028 | LogError("NULL link"); |
AzureIoTClient | 28:add19eb7defa | 1029 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 1030 | } |
AzureIoTClient | 28:add19eb7defa | 1031 | else |
AzureIoTClient | 28:add19eb7defa | 1032 | { |
AzureIoTClient | 28:add19eb7defa | 1033 | link->max_message_size = max_message_size; |
AzureIoTClient | 28:add19eb7defa | 1034 | result = 0; |
AzureIoTClient | 28:add19eb7defa | 1035 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 1036 | |
AzureIoTClient | 28:add19eb7defa | 1037 | return result; |
Azure.IoT Build | 0:6ae2f7bca550 | 1038 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 1039 | |
Azure.IoT Build | 0:6ae2f7bca550 | 1040 | int link_get_max_message_size(LINK_HANDLE link, uint64_t* max_message_size) |
Azure.IoT Build | 0:6ae2f7bca550 | 1041 | { |
AzureIoTClient | 28:add19eb7defa | 1042 | int result; |
Azure.IoT Build | 0:6ae2f7bca550 | 1043 | |
AzureIoTClient | 28:add19eb7defa | 1044 | if ((link == NULL) || |
AzureIoTClient | 28:add19eb7defa | 1045 | (max_message_size == NULL)) |
AzureIoTClient | 28:add19eb7defa | 1046 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1047 | LogError("Bad arguments: link = %p, max_message_size = %p", |
AzureIoTClient | 41:0e723f9cbd89 | 1048 | link, max_message_size); |
AzureIoTClient | 28:add19eb7defa | 1049 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 1050 | } |
AzureIoTClient | 28:add19eb7defa | 1051 | else |
AzureIoTClient | 28:add19eb7defa | 1052 | { |
AzureIoTClient | 28:add19eb7defa | 1053 | *max_message_size = link->max_message_size; |
AzureIoTClient | 28:add19eb7defa | 1054 | result = 0; |
AzureIoTClient | 28:add19eb7defa | 1055 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 1056 | |
AzureIoTClient | 28:add19eb7defa | 1057 | return result; |
Azure.IoT Build | 0:6ae2f7bca550 | 1058 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 1059 | |
AzureIoTClient | 24:2c59c2d43ebf | 1060 | int link_get_peer_max_message_size(LINK_HANDLE link, uint64_t* peer_max_message_size) |
AzureIoTClient | 24:2c59c2d43ebf | 1061 | { |
AzureIoTClient | 28:add19eb7defa | 1062 | int result; |
AzureIoTClient | 24:2c59c2d43ebf | 1063 | |
AzureIoTClient | 28:add19eb7defa | 1064 | if ((link == NULL) || |
AzureIoTClient | 28:add19eb7defa | 1065 | (peer_max_message_size == NULL)) |
AzureIoTClient | 28:add19eb7defa | 1066 | { |
AzureIoTClient | 28:add19eb7defa | 1067 | LogError("Bad arguments: link = %p, peer_max_message_size = %p", |
AzureIoTClient | 28:add19eb7defa | 1068 | link, peer_max_message_size); |
AzureIoTClient | 28:add19eb7defa | 1069 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 1070 | } |
AzureIoTClient | 28:add19eb7defa | 1071 | else if ((link->link_state != LINK_STATE_ATTACHED) && |
AzureIoTClient | 28:add19eb7defa | 1072 | (link->link_state != LINK_STATE_HALF_ATTACHED_ATTACH_RECEIVED)) |
AzureIoTClient | 28:add19eb7defa | 1073 | { |
AzureIoTClient | 28:add19eb7defa | 1074 | LogError("Attempting to read peer max message size before it was received"); |
AzureIoTClient | 28:add19eb7defa | 1075 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 1076 | } |
AzureIoTClient | 28:add19eb7defa | 1077 | else |
AzureIoTClient | 28:add19eb7defa | 1078 | { |
AzureIoTClient | 28:add19eb7defa | 1079 | *peer_max_message_size = link->peer_max_message_size; |
AzureIoTClient | 28:add19eb7defa | 1080 | result = 0; |
AzureIoTClient | 28:add19eb7defa | 1081 | } |
AzureIoTClient | 24:2c59c2d43ebf | 1082 | |
AzureIoTClient | 28:add19eb7defa | 1083 | return result; |
AzureIoTClient | 24:2c59c2d43ebf | 1084 | } |
AzureIoTClient | 24:2c59c2d43ebf | 1085 | |
Azure.IoT Build | 0:6ae2f7bca550 | 1086 | int link_set_attach_properties(LINK_HANDLE link, fields attach_properties) |
Azure.IoT Build | 0:6ae2f7bca550 | 1087 | { |
Azure.IoT Build | 0:6ae2f7bca550 | 1088 | int result; |
Azure.IoT Build | 0:6ae2f7bca550 | 1089 | |
Azure.IoT Build | 0:6ae2f7bca550 | 1090 | if (link == NULL) |
Azure.IoT Build | 0:6ae2f7bca550 | 1091 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1092 | LogError("NULL link"); |
AzureIoTClient | 19:000ab4e6a2c1 | 1093 | result = __FAILURE__; |
Azure.IoT Build | 0:6ae2f7bca550 | 1094 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 1095 | else |
Azure.IoT Build | 0:6ae2f7bca550 | 1096 | { |
Azure.IoT Build | 0:6ae2f7bca550 | 1097 | link->attach_properties = amqpvalue_clone(attach_properties); |
Azure.IoT Build | 0:6ae2f7bca550 | 1098 | if (link->attach_properties == NULL) |
Azure.IoT Build | 0:6ae2f7bca550 | 1099 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1100 | LogError("Failed cloning attach properties"); |
AzureIoTClient | 19:000ab4e6a2c1 | 1101 | result = __FAILURE__; |
Azure.IoT Build | 0:6ae2f7bca550 | 1102 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 1103 | else |
Azure.IoT Build | 0:6ae2f7bca550 | 1104 | { |
Azure.IoT Build | 0:6ae2f7bca550 | 1105 | result = 0; |
Azure.IoT Build | 0:6ae2f7bca550 | 1106 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 1107 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 1108 | |
Azure.IoT Build | 0:6ae2f7bca550 | 1109 | return result; |
Azure.IoT Build | 0:6ae2f7bca550 | 1110 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 1111 | |
AzureIoTClient | 41:0e723f9cbd89 | 1112 | int link_set_max_link_credit(LINK_HANDLE link, uint32_t max_link_credit) |
AzureIoTClient | 41:0e723f9cbd89 | 1113 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1114 | int result; |
AzureIoTClient | 41:0e723f9cbd89 | 1115 | |
AzureIoTClient | 41:0e723f9cbd89 | 1116 | if (link == NULL) |
AzureIoTClient | 41:0e723f9cbd89 | 1117 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1118 | result = __FAILURE__; |
AzureIoTClient | 41:0e723f9cbd89 | 1119 | } |
AzureIoTClient | 41:0e723f9cbd89 | 1120 | else |
AzureIoTClient | 41:0e723f9cbd89 | 1121 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1122 | link->max_link_credit = max_link_credit; |
AzureIoTClient | 41:0e723f9cbd89 | 1123 | result = 0; |
AzureIoTClient | 41:0e723f9cbd89 | 1124 | } |
AzureIoTClient | 41:0e723f9cbd89 | 1125 | |
AzureIoTClient | 41:0e723f9cbd89 | 1126 | return result; |
AzureIoTClient | 41:0e723f9cbd89 | 1127 | } |
AzureIoTClient | 41:0e723f9cbd89 | 1128 | |
Azure.IoT Build | 0:6ae2f7bca550 | 1129 | 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 | 1130 | { |
AzureIoTClient | 28:add19eb7defa | 1131 | int result; |
Azure.IoT Build | 0:6ae2f7bca550 | 1132 | |
AzureIoTClient | 41:0e723f9cbd89 | 1133 | if (link == NULL) |
AzureIoTClient | 28:add19eb7defa | 1134 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1135 | LogError("NULL link"); |
AzureIoTClient | 41:0e723f9cbd89 | 1136 | result = __FAILURE__; |
AzureIoTClient | 41:0e723f9cbd89 | 1137 | } |
AzureIoTClient | 41:0e723f9cbd89 | 1138 | else if (link->is_closed) |
AzureIoTClient | 41:0e723f9cbd89 | 1139 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1140 | LogError("Already attached"); |
AzureIoTClient | 28:add19eb7defa | 1141 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 1142 | } |
AzureIoTClient | 28:add19eb7defa | 1143 | else |
AzureIoTClient | 28:add19eb7defa | 1144 | { |
AzureIoTClient | 28:add19eb7defa | 1145 | if (!link->is_underlying_session_begun) |
AzureIoTClient | 28:add19eb7defa | 1146 | { |
AzureIoTClient | 28:add19eb7defa | 1147 | link->on_link_state_changed = on_link_state_changed; |
AzureIoTClient | 28:add19eb7defa | 1148 | link->on_transfer_received = on_transfer_received; |
AzureIoTClient | 28:add19eb7defa | 1149 | link->on_link_flow_on = on_link_flow_on; |
AzureIoTClient | 28:add19eb7defa | 1150 | link->callback_context = callback_context; |
Azure.IoT Build | 0:6ae2f7bca550 | 1151 | |
AzureIoTClient | 28:add19eb7defa | 1152 | if (session_begin(link->session) != 0) |
AzureIoTClient | 28:add19eb7defa | 1153 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1154 | LogError("Begin session failed"); |
AzureIoTClient | 28:add19eb7defa | 1155 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 1156 | } |
AzureIoTClient | 28:add19eb7defa | 1157 | else |
AzureIoTClient | 28:add19eb7defa | 1158 | { |
AzureIoTClient | 28:add19eb7defa | 1159 | link->is_underlying_session_begun = true; |
Azure.IoT Build | 0:6ae2f7bca550 | 1160 | |
AzureIoTClient | 28:add19eb7defa | 1161 | if (session_start_link_endpoint(link->link_endpoint, link_frame_received, on_session_state_changed, on_session_flow_on, link) != 0) |
AzureIoTClient | 28:add19eb7defa | 1162 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1163 | LogError("Binding link endpoint to session failed"); |
AzureIoTClient | 28:add19eb7defa | 1164 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 1165 | } |
AzureIoTClient | 28:add19eb7defa | 1166 | else |
AzureIoTClient | 28:add19eb7defa | 1167 | { |
AzureIoTClient | 12:b30dacf113f2 | 1168 | link->received_payload_size = 0; |
AzureIoTClient | 12:b30dacf113f2 | 1169 | |
AzureIoTClient | 28:add19eb7defa | 1170 | result = 0; |
AzureIoTClient | 28:add19eb7defa | 1171 | } |
AzureIoTClient | 28:add19eb7defa | 1172 | } |
AzureIoTClient | 28:add19eb7defa | 1173 | } |
AzureIoTClient | 28:add19eb7defa | 1174 | else |
AzureIoTClient | 28:add19eb7defa | 1175 | { |
AzureIoTClient | 28:add19eb7defa | 1176 | result = 0; |
AzureIoTClient | 28:add19eb7defa | 1177 | } |
AzureIoTClient | 28:add19eb7defa | 1178 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 1179 | |
AzureIoTClient | 28:add19eb7defa | 1180 | return result; |
Azure.IoT Build | 0:6ae2f7bca550 | 1181 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 1182 | |
AzureIoTClient | 43:4c1e4e94cdd3 | 1183 | int link_detach(LINK_HANDLE link, bool close, const char* error_condition, const char* error_description, AMQP_VALUE info) |
Azure.IoT Build | 0:6ae2f7bca550 | 1184 | { |
AzureIoTClient | 28:add19eb7defa | 1185 | int result; |
Azure.IoT Build | 0:6ae2f7bca550 | 1186 | |
AzureIoTClient | 43:4c1e4e94cdd3 | 1187 | (void)error_condition; |
AzureIoTClient | 43:4c1e4e94cdd3 | 1188 | (void)error_description; |
AzureIoTClient | 43:4c1e4e94cdd3 | 1189 | (void)info; |
AzureIoTClient | 43:4c1e4e94cdd3 | 1190 | |
AzureIoTClient | 41:0e723f9cbd89 | 1191 | if (link == NULL) |
AzureIoTClient | 12:b30dacf113f2 | 1192 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1193 | LogError("NULL link"); |
AzureIoTClient | 28:add19eb7defa | 1194 | result = __FAILURE__; |
AzureIoTClient | 28:add19eb7defa | 1195 | } |
AzureIoTClient | 41:0e723f9cbd89 | 1196 | else if (link->is_closed) |
AzureIoTClient | 41:0e723f9cbd89 | 1197 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1198 | result = 0; |
AzureIoTClient | 41:0e723f9cbd89 | 1199 | } |
AzureIoTClient | 28:add19eb7defa | 1200 | else |
AzureIoTClient | 28:add19eb7defa | 1201 | { |
AzureIoTClient | 43:4c1e4e94cdd3 | 1202 | ERROR_HANDLE error; |
AzureIoTClient | 43:4c1e4e94cdd3 | 1203 | |
AzureIoTClient | 43:4c1e4e94cdd3 | 1204 | if (error_condition != NULL) |
AzureIoTClient | 43:4c1e4e94cdd3 | 1205 | { |
AzureIoTClient | 43:4c1e4e94cdd3 | 1206 | error = error_create(error_condition); |
AzureIoTClient | 43:4c1e4e94cdd3 | 1207 | if (error == NULL) |
AzureIoTClient | 43:4c1e4e94cdd3 | 1208 | { |
AzureIoTClient | 43:4c1e4e94cdd3 | 1209 | LogInfo("Cannot create error for detach, detaching without error anyhow"); |
AzureIoTClient | 43:4c1e4e94cdd3 | 1210 | } |
AzureIoTClient | 43:4c1e4e94cdd3 | 1211 | else |
AzureIoTClient | 43:4c1e4e94cdd3 | 1212 | { |
AzureIoTClient | 43:4c1e4e94cdd3 | 1213 | if (error_description != NULL) |
AzureIoTClient | 43:4c1e4e94cdd3 | 1214 | { |
AzureIoTClient | 43:4c1e4e94cdd3 | 1215 | if (error_set_description(error, error_description) != 0) |
AzureIoTClient | 43:4c1e4e94cdd3 | 1216 | { |
AzureIoTClient | 43:4c1e4e94cdd3 | 1217 | LogInfo("Cannot set error description on detach error, detaching anyhow"); |
AzureIoTClient | 43:4c1e4e94cdd3 | 1218 | } |
AzureIoTClient | 43:4c1e4e94cdd3 | 1219 | } |
AzureIoTClient | 43:4c1e4e94cdd3 | 1220 | |
AzureIoTClient | 43:4c1e4e94cdd3 | 1221 | if (info != NULL) |
AzureIoTClient | 43:4c1e4e94cdd3 | 1222 | { |
AzureIoTClient | 43:4c1e4e94cdd3 | 1223 | if (error_set_info(error, info) != 0) |
AzureIoTClient | 43:4c1e4e94cdd3 | 1224 | { |
AzureIoTClient | 43:4c1e4e94cdd3 | 1225 | LogInfo("Cannot set info map on detach error, detaching anyhow"); |
AzureIoTClient | 43:4c1e4e94cdd3 | 1226 | } |
AzureIoTClient | 43:4c1e4e94cdd3 | 1227 | } |
AzureIoTClient | 43:4c1e4e94cdd3 | 1228 | } |
AzureIoTClient | 43:4c1e4e94cdd3 | 1229 | } |
AzureIoTClient | 43:4c1e4e94cdd3 | 1230 | else |
AzureIoTClient | 43:4c1e4e94cdd3 | 1231 | { |
AzureIoTClient | 43:4c1e4e94cdd3 | 1232 | error = NULL; |
AzureIoTClient | 43:4c1e4e94cdd3 | 1233 | } |
AzureIoTClient | 43:4c1e4e94cdd3 | 1234 | |
AzureIoTClient | 12:b30dacf113f2 | 1235 | switch (link->link_state) |
AzureIoTClient | 12:b30dacf113f2 | 1236 | { |
AzureIoTClient | 24:2c59c2d43ebf | 1237 | case LINK_STATE_HALF_ATTACHED_ATTACH_SENT: |
AzureIoTClient | 28:add19eb7defa | 1238 | case LINK_STATE_HALF_ATTACHED_ATTACH_RECEIVED: |
AzureIoTClient | 12:b30dacf113f2 | 1239 | /* Sending detach when remote is not yet attached */ |
AzureIoTClient | 43:4c1e4e94cdd3 | 1240 | if (send_detach(link, close, error) != 0) |
AzureIoTClient | 12:b30dacf113f2 | 1241 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1242 | LogError("Sending detach frame failed"); |
AzureIoTClient | 19:000ab4e6a2c1 | 1243 | result = __FAILURE__; |
AzureIoTClient | 12:b30dacf113f2 | 1244 | } |
AzureIoTClient | 12:b30dacf113f2 | 1245 | else |
AzureIoTClient | 12:b30dacf113f2 | 1246 | { |
AzureIoTClient | 12:b30dacf113f2 | 1247 | set_link_state(link, LINK_STATE_DETACHED); |
AzureIoTClient | 12:b30dacf113f2 | 1248 | result = 0; |
AzureIoTClient | 12:b30dacf113f2 | 1249 | } |
AzureIoTClient | 12:b30dacf113f2 | 1250 | break; |
AzureIoTClient | 12:b30dacf113f2 | 1251 | |
AzureIoTClient | 12:b30dacf113f2 | 1252 | case LINK_STATE_ATTACHED: |
AzureIoTClient | 12:b30dacf113f2 | 1253 | /* Send detach and wait for remote to respond */ |
AzureIoTClient | 43:4c1e4e94cdd3 | 1254 | if (send_detach(link, close, error) != 0) |
AzureIoTClient | 12:b30dacf113f2 | 1255 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1256 | LogError("Sending detach frame failed"); |
AzureIoTClient | 19:000ab4e6a2c1 | 1257 | result = __FAILURE__; |
AzureIoTClient | 12:b30dacf113f2 | 1258 | } |
AzureIoTClient | 12:b30dacf113f2 | 1259 | else |
AzureIoTClient | 12:b30dacf113f2 | 1260 | { |
AzureIoTClient | 24:2c59c2d43ebf | 1261 | set_link_state(link, LINK_STATE_HALF_ATTACHED_ATTACH_SENT); |
AzureIoTClient | 12:b30dacf113f2 | 1262 | result = 0; |
AzureIoTClient | 12:b30dacf113f2 | 1263 | } |
AzureIoTClient | 12:b30dacf113f2 | 1264 | break; |
AzureIoTClient | 12:b30dacf113f2 | 1265 | |
AzureIoTClient | 12:b30dacf113f2 | 1266 | case LINK_STATE_DETACHED: |
AzureIoTClient | 12:b30dacf113f2 | 1267 | /* Already detached */ |
AzureIoTClient | 12:b30dacf113f2 | 1268 | result = 0; |
AzureIoTClient | 12:b30dacf113f2 | 1269 | break; |
AzureIoTClient | 12:b30dacf113f2 | 1270 | |
AzureIoTClient | 12:b30dacf113f2 | 1271 | default: |
AzureIoTClient | 12:b30dacf113f2 | 1272 | case LINK_STATE_ERROR: |
AzureIoTClient | 12:b30dacf113f2 | 1273 | /* Already detached and in error state */ |
AzureIoTClient | 19:000ab4e6a2c1 | 1274 | result = __FAILURE__; |
AzureIoTClient | 12:b30dacf113f2 | 1275 | break; |
AzureIoTClient | 12:b30dacf113f2 | 1276 | } |
AzureIoTClient | 43:4c1e4e94cdd3 | 1277 | |
AzureIoTClient | 43:4c1e4e94cdd3 | 1278 | if (error != NULL) |
AzureIoTClient | 43:4c1e4e94cdd3 | 1279 | { |
AzureIoTClient | 43:4c1e4e94cdd3 | 1280 | error_destroy(error); |
AzureIoTClient | 43:4c1e4e94cdd3 | 1281 | } |
AzureIoTClient | 28:add19eb7defa | 1282 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 1283 | |
AzureIoTClient | 28:add19eb7defa | 1284 | return result; |
Azure.IoT Build | 0:6ae2f7bca550 | 1285 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 1286 | |
AzureIoTClient | 36:8e1d94b0a70c | 1287 | static bool remove_pending_delivery_condition_function(const void* item, const void* match_context, bool* continue_processing) |
Azure.IoT Build | 0:6ae2f7bca550 | 1288 | { |
AzureIoTClient | 36:8e1d94b0a70c | 1289 | bool result; |
AzureIoTClient | 36:8e1d94b0a70c | 1290 | |
AzureIoTClient | 36:8e1d94b0a70c | 1291 | if (item == match_context) |
AzureIoTClient | 36:8e1d94b0a70c | 1292 | { |
AzureIoTClient | 36:8e1d94b0a70c | 1293 | result = true; |
AzureIoTClient | 36:8e1d94b0a70c | 1294 | *continue_processing = false; |
AzureIoTClient | 36:8e1d94b0a70c | 1295 | } |
AzureIoTClient | 36:8e1d94b0a70c | 1296 | else |
AzureIoTClient | 36:8e1d94b0a70c | 1297 | { |
AzureIoTClient | 36:8e1d94b0a70c | 1298 | result = false; |
AzureIoTClient | 36:8e1d94b0a70c | 1299 | *continue_processing = true; |
AzureIoTClient | 36:8e1d94b0a70c | 1300 | } |
AzureIoTClient | 36:8e1d94b0a70c | 1301 | |
AzureIoTClient | 36:8e1d94b0a70c | 1302 | return result; |
AzureIoTClient | 36:8e1d94b0a70c | 1303 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 1304 | |
AzureIoTClient | 36:8e1d94b0a70c | 1305 | static void link_transfer_cancel_handler(ASYNC_OPERATION_HANDLE link_transfer_operation) |
AzureIoTClient | 36:8e1d94b0a70c | 1306 | { |
AzureIoTClient | 36:8e1d94b0a70c | 1307 | DELIVERY_INSTANCE* pending_delivery = GET_ASYNC_OPERATION_CONTEXT(DELIVERY_INSTANCE, link_transfer_operation); |
AzureIoTClient | 36:8e1d94b0a70c | 1308 | if (pending_delivery->on_delivery_settled != NULL) |
AzureIoTClient | 28:add19eb7defa | 1309 | { |
AzureIoTClient | 36:8e1d94b0a70c | 1310 | pending_delivery->on_delivery_settled(pending_delivery->callback_context, pending_delivery->delivery_id, LINK_DELIVERY_SETTLE_REASON_CANCELLED, NULL); |
AzureIoTClient | 36:8e1d94b0a70c | 1311 | } |
AzureIoTClient | 46:01f7ca900e07 | 1312 | |
AzureIoTClient | 36:8e1d94b0a70c | 1313 | (void)singlylinkedlist_remove_if(((LINK_HANDLE)pending_delivery->link)->pending_deliveries, remove_pending_delivery_condition_function, pending_delivery); |
AzureIoTClient | 37:c923ba7f6cf9 | 1314 | |
AzureIoTClient | 37:c923ba7f6cf9 | 1315 | async_operation_destroy(link_transfer_operation); |
AzureIoTClient | 36:8e1d94b0a70c | 1316 | } |
AzureIoTClient | 36:8e1d94b0a70c | 1317 | |
AzureIoTClient | 36:8e1d94b0a70c | 1318 | ASYNC_OPERATION_HANDLE 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, LINK_TRANSFER_RESULT* link_transfer_error, tickcounter_ms_t timeout) |
AzureIoTClient | 36:8e1d94b0a70c | 1319 | { |
AzureIoTClient | 36:8e1d94b0a70c | 1320 | ASYNC_OPERATION_HANDLE result; |
AzureIoTClient | 36:8e1d94b0a70c | 1321 | |
AzureIoTClient | 36:8e1d94b0a70c | 1322 | if ((link == NULL) || |
AzureIoTClient | 36:8e1d94b0a70c | 1323 | (link_transfer_error == NULL)) |
AzureIoTClient | 36:8e1d94b0a70c | 1324 | { |
AzureIoTClient | 36:8e1d94b0a70c | 1325 | if (link_transfer_error != NULL) |
AzureIoTClient | 36:8e1d94b0a70c | 1326 | { |
AzureIoTClient | 36:8e1d94b0a70c | 1327 | *link_transfer_error = LINK_TRANSFER_ERROR; |
AzureIoTClient | 36:8e1d94b0a70c | 1328 | } |
AzureIoTClient | 36:8e1d94b0a70c | 1329 | |
AzureIoTClient | 41:0e723f9cbd89 | 1330 | LogError("Invalid arguments: link = %p, link_transfer_error = %p", |
AzureIoTClient | 41:0e723f9cbd89 | 1331 | link, link_transfer_error); |
AzureIoTClient | 36:8e1d94b0a70c | 1332 | result = NULL; |
AzureIoTClient | 28:add19eb7defa | 1333 | } |
AzureIoTClient | 28:add19eb7defa | 1334 | else |
AzureIoTClient | 28:add19eb7defa | 1335 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1336 | if (link->role != role_sender) |
AzureIoTClient | 28:add19eb7defa | 1337 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1338 | LogError("Link is not a sender link"); |
AzureIoTClient | 36:8e1d94b0a70c | 1339 | *link_transfer_error = LINK_TRANSFER_ERROR; |
AzureIoTClient | 36:8e1d94b0a70c | 1340 | result = NULL; |
AzureIoTClient | 28:add19eb7defa | 1341 | } |
AzureIoTClient | 41:0e723f9cbd89 | 1342 | else if (link->link_state != LINK_STATE_ATTACHED) |
AzureIoTClient | 41:0e723f9cbd89 | 1343 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1344 | LogError("Link is not attached"); |
AzureIoTClient | 41:0e723f9cbd89 | 1345 | *link_transfer_error = LINK_TRANSFER_ERROR; |
AzureIoTClient | 41:0e723f9cbd89 | 1346 | result = NULL; |
AzureIoTClient | 41:0e723f9cbd89 | 1347 | } |
AzureIoTClient | 41:0e723f9cbd89 | 1348 | else if (link->current_link_credit == 0) |
AzureIoTClient | 28:add19eb7defa | 1349 | { |
AzureIoTClient | 36:8e1d94b0a70c | 1350 | *link_transfer_error = LINK_TRANSFER_BUSY; |
AzureIoTClient | 36:8e1d94b0a70c | 1351 | result = NULL; |
AzureIoTClient | 28:add19eb7defa | 1352 | } |
AzureIoTClient | 28:add19eb7defa | 1353 | else |
AzureIoTClient | 28:add19eb7defa | 1354 | { |
AzureIoTClient | 36:8e1d94b0a70c | 1355 | result = CREATE_ASYNC_OPERATION(DELIVERY_INSTANCE, link_transfer_cancel_handler); |
AzureIoTClient | 41:0e723f9cbd89 | 1356 | if (result == NULL) |
AzureIoTClient | 41:0e723f9cbd89 | 1357 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1358 | LogError("Error creating async operation"); |
AzureIoTClient | 41:0e723f9cbd89 | 1359 | *link_transfer_error = LINK_TRANSFER_ERROR; |
AzureIoTClient | 41:0e723f9cbd89 | 1360 | } |
AzureIoTClient | 41:0e723f9cbd89 | 1361 | else |
AzureIoTClient | 28:add19eb7defa | 1362 | { |
AzureIoTClient | 36:8e1d94b0a70c | 1363 | TRANSFER_HANDLE transfer = transfer_create(0); |
AzureIoTClient | 36:8e1d94b0a70c | 1364 | if (transfer == NULL) |
AzureIoTClient | 28:add19eb7defa | 1365 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1366 | LogError("Error creating transfer"); |
AzureIoTClient | 36:8e1d94b0a70c | 1367 | *link_transfer_error = LINK_TRANSFER_ERROR; |
AzureIoTClient | 36:8e1d94b0a70c | 1368 | async_operation_destroy(result); |
AzureIoTClient | 36:8e1d94b0a70c | 1369 | result = NULL; |
AzureIoTClient | 28:add19eb7defa | 1370 | } |
AzureIoTClient | 28:add19eb7defa | 1371 | else |
AzureIoTClient | 28:add19eb7defa | 1372 | { |
AzureIoTClient | 36:8e1d94b0a70c | 1373 | sequence_no delivery_count = link->delivery_count + 1; |
AzureIoTClient | 36:8e1d94b0a70c | 1374 | unsigned char delivery_tag_bytes[sizeof(delivery_count)]; |
AzureIoTClient | 36:8e1d94b0a70c | 1375 | delivery_tag delivery_tag; |
AzureIoTClient | 36:8e1d94b0a70c | 1376 | bool settled; |
AzureIoTClient | 36:8e1d94b0a70c | 1377 | |
AzureIoTClient | 36:8e1d94b0a70c | 1378 | (void)memcpy(delivery_tag_bytes, &delivery_count, sizeof(delivery_count)); |
AzureIoTClient | 36:8e1d94b0a70c | 1379 | |
AzureIoTClient | 36:8e1d94b0a70c | 1380 | delivery_tag.bytes = &delivery_tag_bytes; |
AzureIoTClient | 36:8e1d94b0a70c | 1381 | delivery_tag.length = sizeof(delivery_tag_bytes); |
Azure.IoT Build | 0:6ae2f7bca550 | 1382 | |
AzureIoTClient | 36:8e1d94b0a70c | 1383 | if (link->snd_settle_mode == sender_settle_mode_unsettled) |
AzureIoTClient | 36:8e1d94b0a70c | 1384 | { |
AzureIoTClient | 36:8e1d94b0a70c | 1385 | settled = false; |
AzureIoTClient | 36:8e1d94b0a70c | 1386 | } |
AzureIoTClient | 36:8e1d94b0a70c | 1387 | else |
AzureIoTClient | 36:8e1d94b0a70c | 1388 | { |
AzureIoTClient | 36:8e1d94b0a70c | 1389 | settled = true; |
AzureIoTClient | 36:8e1d94b0a70c | 1390 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 1391 | |
AzureIoTClient | 41:0e723f9cbd89 | 1392 | if (transfer_set_delivery_tag(transfer, delivery_tag) != 0) |
AzureIoTClient | 41:0e723f9cbd89 | 1393 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1394 | LogError("Failed setting delivery tag"); |
AzureIoTClient | 41:0e723f9cbd89 | 1395 | *link_transfer_error = LINK_TRANSFER_ERROR; |
AzureIoTClient | 41:0e723f9cbd89 | 1396 | async_operation_destroy(result); |
AzureIoTClient | 41:0e723f9cbd89 | 1397 | result = NULL; |
AzureIoTClient | 41:0e723f9cbd89 | 1398 | } |
AzureIoTClient | 41:0e723f9cbd89 | 1399 | else if (transfer_set_message_format(transfer, message_format) != 0) |
AzureIoTClient | 28:add19eb7defa | 1400 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1401 | LogError("Failed setting message format"); |
AzureIoTClient | 41:0e723f9cbd89 | 1402 | *link_transfer_error = LINK_TRANSFER_ERROR; |
AzureIoTClient | 41:0e723f9cbd89 | 1403 | async_operation_destroy(result); |
AzureIoTClient | 41:0e723f9cbd89 | 1404 | result = NULL; |
AzureIoTClient | 41:0e723f9cbd89 | 1405 | } |
AzureIoTClient | 41:0e723f9cbd89 | 1406 | else if (transfer_set_settled(transfer, settled) != 0) |
AzureIoTClient | 41:0e723f9cbd89 | 1407 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1408 | LogError("Failed setting settled flag"); |
AzureIoTClient | 36:8e1d94b0a70c | 1409 | *link_transfer_error = LINK_TRANSFER_ERROR; |
AzureIoTClient | 36:8e1d94b0a70c | 1410 | async_operation_destroy(result); |
AzureIoTClient | 36:8e1d94b0a70c | 1411 | result = NULL; |
AzureIoTClient | 28:add19eb7defa | 1412 | } |
AzureIoTClient | 28:add19eb7defa | 1413 | else |
AzureIoTClient | 28:add19eb7defa | 1414 | { |
AzureIoTClient | 36:8e1d94b0a70c | 1415 | AMQP_VALUE transfer_value = amqpvalue_create_transfer(transfer); |
AzureIoTClient | 36:8e1d94b0a70c | 1416 | if (transfer_value == NULL) |
AzureIoTClient | 28:add19eb7defa | 1417 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1418 | LogError("Failed creating transfer performative AMQP value"); |
AzureIoTClient | 36:8e1d94b0a70c | 1419 | *link_transfer_error = LINK_TRANSFER_ERROR; |
AzureIoTClient | 36:8e1d94b0a70c | 1420 | async_operation_destroy(result); |
AzureIoTClient | 36:8e1d94b0a70c | 1421 | result = NULL; |
AzureIoTClient | 28:add19eb7defa | 1422 | } |
AzureIoTClient | 28:add19eb7defa | 1423 | else |
AzureIoTClient | 28:add19eb7defa | 1424 | { |
AzureIoTClient | 36:8e1d94b0a70c | 1425 | DELIVERY_INSTANCE* pending_delivery = GET_ASYNC_OPERATION_CONTEXT(DELIVERY_INSTANCE, result); |
AzureIoTClient | 36:8e1d94b0a70c | 1426 | if (pending_delivery == NULL) |
AzureIoTClient | 28:add19eb7defa | 1427 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1428 | LogError("Failed getting pending delivery"); |
AzureIoTClient | 36:8e1d94b0a70c | 1429 | *link_transfer_error = LINK_TRANSFER_ERROR; |
AzureIoTClient | 36:8e1d94b0a70c | 1430 | async_operation_destroy(result); |
AzureIoTClient | 36:8e1d94b0a70c | 1431 | result = NULL; |
AzureIoTClient | 28:add19eb7defa | 1432 | } |
AzureIoTClient | 28:add19eb7defa | 1433 | else |
AzureIoTClient | 28:add19eb7defa | 1434 | { |
AzureIoTClient | 36:8e1d94b0a70c | 1435 | if (tickcounter_get_current_ms(link->tick_counter, &pending_delivery->start_tick) != 0) |
AzureIoTClient | 28:add19eb7defa | 1436 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1437 | LogError("Failed getting current tick"); |
AzureIoTClient | 36:8e1d94b0a70c | 1438 | *link_transfer_error = LINK_TRANSFER_ERROR; |
AzureIoTClient | 36:8e1d94b0a70c | 1439 | async_operation_destroy(result); |
AzureIoTClient | 36:8e1d94b0a70c | 1440 | result = NULL; |
AzureIoTClient | 34:6be9c2058664 | 1441 | } |
AzureIoTClient | 34:6be9c2058664 | 1442 | else |
AzureIoTClient | 34:6be9c2058664 | 1443 | { |
AzureIoTClient | 36:8e1d94b0a70c | 1444 | LIST_ITEM_HANDLE delivery_instance_list_item; |
AzureIoTClient | 36:8e1d94b0a70c | 1445 | pending_delivery->timeout = timeout; |
AzureIoTClient | 36:8e1d94b0a70c | 1446 | pending_delivery->on_delivery_settled = on_delivery_settled; |
AzureIoTClient | 36:8e1d94b0a70c | 1447 | pending_delivery->callback_context = callback_context; |
AzureIoTClient | 36:8e1d94b0a70c | 1448 | pending_delivery->link = link; |
AzureIoTClient | 36:8e1d94b0a70c | 1449 | delivery_instance_list_item = singlylinkedlist_add(link->pending_deliveries, result); |
Azure.IoT Build | 0:6ae2f7bca550 | 1450 | |
AzureIoTClient | 36:8e1d94b0a70c | 1451 | if (delivery_instance_list_item == NULL) |
AzureIoTClient | 36:8e1d94b0a70c | 1452 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1453 | LogError("Failed adding delivery to list"); |
AzureIoTClient | 36:8e1d94b0a70c | 1454 | *link_transfer_error = LINK_TRANSFER_ERROR; |
AzureIoTClient | 36:8e1d94b0a70c | 1455 | async_operation_destroy(result); |
AzureIoTClient | 36:8e1d94b0a70c | 1456 | result = NULL; |
AzureIoTClient | 36:8e1d94b0a70c | 1457 | } |
AzureIoTClient | 36:8e1d94b0a70c | 1458 | else |
AzureIoTClient | 36:8e1d94b0a70c | 1459 | { |
AzureIoTClient | 36:8e1d94b0a70c | 1460 | /* here we should feed data to the transfer frame */ |
AzureIoTClient | 36:8e1d94b0a70c | 1461 | 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 | 36:8e1d94b0a70c | 1462 | { |
AzureIoTClient | 36:8e1d94b0a70c | 1463 | default: |
AzureIoTClient | 36:8e1d94b0a70c | 1464 | case SESSION_SEND_TRANSFER_ERROR: |
AzureIoTClient | 41:0e723f9cbd89 | 1465 | LogError("Failed session send transfer"); |
AzureIoTClient | 41:0e723f9cbd89 | 1466 | if (singlylinkedlist_remove(link->pending_deliveries, delivery_instance_list_item) != 0) |
AzureIoTClient | 41:0e723f9cbd89 | 1467 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1468 | LogError("Error removing pending delivery from the list"); |
AzureIoTClient | 41:0e723f9cbd89 | 1469 | } |
AzureIoTClient | 41:0e723f9cbd89 | 1470 | |
AzureIoTClient | 36:8e1d94b0a70c | 1471 | *link_transfer_error = LINK_TRANSFER_ERROR; |
AzureIoTClient | 36:8e1d94b0a70c | 1472 | async_operation_destroy(result); |
AzureIoTClient | 36:8e1d94b0a70c | 1473 | result = NULL; |
AzureIoTClient | 36:8e1d94b0a70c | 1474 | break; |
Azure.IoT Build | 0:6ae2f7bca550 | 1475 | |
AzureIoTClient | 36:8e1d94b0a70c | 1476 | case SESSION_SEND_TRANSFER_BUSY: |
AzureIoTClient | 36:8e1d94b0a70c | 1477 | /* Ensure we remove from list again since sender will attempt to transfer again on flow on */ |
AzureIoTClient | 41:0e723f9cbd89 | 1478 | LogError("Failed session send transfer"); |
AzureIoTClient | 41:0e723f9cbd89 | 1479 | if (singlylinkedlist_remove(link->pending_deliveries, delivery_instance_list_item) != 0) |
AzureIoTClient | 41:0e723f9cbd89 | 1480 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1481 | LogError("Error removing pending delivery from the list"); |
AzureIoTClient | 41:0e723f9cbd89 | 1482 | } |
AzureIoTClient | 41:0e723f9cbd89 | 1483 | |
AzureIoTClient | 36:8e1d94b0a70c | 1484 | *link_transfer_error = LINK_TRANSFER_BUSY; |
AzureIoTClient | 36:8e1d94b0a70c | 1485 | async_operation_destroy(result); |
AzureIoTClient | 36:8e1d94b0a70c | 1486 | result = NULL; |
AzureIoTClient | 36:8e1d94b0a70c | 1487 | break; |
AzureIoTClient | 36:8e1d94b0a70c | 1488 | |
AzureIoTClient | 36:8e1d94b0a70c | 1489 | case SESSION_SEND_TRANSFER_OK: |
AzureIoTClient | 36:8e1d94b0a70c | 1490 | link->delivery_count = delivery_count; |
AzureIoTClient | 41:0e723f9cbd89 | 1491 | link->current_link_credit--; |
AzureIoTClient | 36:8e1d94b0a70c | 1492 | break; |
AzureIoTClient | 36:8e1d94b0a70c | 1493 | } |
AzureIoTClient | 34:6be9c2058664 | 1494 | } |
AzureIoTClient | 28:add19eb7defa | 1495 | } |
AzureIoTClient | 28:add19eb7defa | 1496 | } |
AzureIoTClient | 36:8e1d94b0a70c | 1497 | |
AzureIoTClient | 36:8e1d94b0a70c | 1498 | amqpvalue_destroy(transfer_value); |
AzureIoTClient | 28:add19eb7defa | 1499 | } |
AzureIoTClient | 28:add19eb7defa | 1500 | } |
AzureIoTClient | 36:8e1d94b0a70c | 1501 | |
AzureIoTClient | 36:8e1d94b0a70c | 1502 | transfer_destroy(transfer); |
AzureIoTClient | 28:add19eb7defa | 1503 | } |
AzureIoTClient | 28:add19eb7defa | 1504 | } |
AzureIoTClient | 28:add19eb7defa | 1505 | } |
AzureIoTClient | 28:add19eb7defa | 1506 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 1507 | |
AzureIoTClient | 28:add19eb7defa | 1508 | return result; |
Azure.IoT Build | 0:6ae2f7bca550 | 1509 | } |
AzureIoTClient | 20:206846c14c80 | 1510 | |
AzureIoTClient | 20:206846c14c80 | 1511 | int link_get_name(LINK_HANDLE link, const char** link_name) |
AzureIoTClient | 20:206846c14c80 | 1512 | { |
AzureIoTClient | 20:206846c14c80 | 1513 | int result; |
AzureIoTClient | 20:206846c14c80 | 1514 | |
AzureIoTClient | 20:206846c14c80 | 1515 | if (link == NULL) |
AzureIoTClient | 20:206846c14c80 | 1516 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1517 | LogError("NULL link"); |
AzureIoTClient | 20:206846c14c80 | 1518 | result = __FAILURE__; |
AzureIoTClient | 20:206846c14c80 | 1519 | } |
AzureIoTClient | 20:206846c14c80 | 1520 | else |
AzureIoTClient | 20:206846c14c80 | 1521 | { |
AzureIoTClient | 20:206846c14c80 | 1522 | *link_name = link->name; |
AzureIoTClient | 20:206846c14c80 | 1523 | result = 0; |
AzureIoTClient | 20:206846c14c80 | 1524 | } |
AzureIoTClient | 20:206846c14c80 | 1525 | |
AzureIoTClient | 20:206846c14c80 | 1526 | return result; |
AzureIoTClient | 20:206846c14c80 | 1527 | } |
AzureIoTClient | 20:206846c14c80 | 1528 | |
AzureIoTClient | 20:206846c14c80 | 1529 | int link_get_received_message_id(LINK_HANDLE link, delivery_number* message_id) |
AzureIoTClient | 20:206846c14c80 | 1530 | { |
AzureIoTClient | 20:206846c14c80 | 1531 | int result; |
AzureIoTClient | 20:206846c14c80 | 1532 | |
AzureIoTClient | 20:206846c14c80 | 1533 | if (link == NULL) |
AzureIoTClient | 20:206846c14c80 | 1534 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1535 | LogError("NULL link"); |
AzureIoTClient | 20:206846c14c80 | 1536 | result = __FAILURE__; |
AzureIoTClient | 20:206846c14c80 | 1537 | } |
AzureIoTClient | 20:206846c14c80 | 1538 | else |
AzureIoTClient | 20:206846c14c80 | 1539 | { |
AzureIoTClient | 20:206846c14c80 | 1540 | *message_id = link->received_delivery_id; |
AzureIoTClient | 20:206846c14c80 | 1541 | result = 0; |
AzureIoTClient | 20:206846c14c80 | 1542 | } |
AzureIoTClient | 20:206846c14c80 | 1543 | |
AzureIoTClient | 20:206846c14c80 | 1544 | return result; |
AzureIoTClient | 20:206846c14c80 | 1545 | } |
AzureIoTClient | 20:206846c14c80 | 1546 | |
AzureIoTClient | 20:206846c14c80 | 1547 | int link_send_disposition(LINK_HANDLE link, delivery_number message_id, AMQP_VALUE delivery_state) |
AzureIoTClient | 20:206846c14c80 | 1548 | { |
AzureIoTClient | 20:206846c14c80 | 1549 | int result; |
AzureIoTClient | 41:0e723f9cbd89 | 1550 | |
AzureIoTClient | 20:206846c14c80 | 1551 | if (delivery_state == NULL) |
AzureIoTClient | 20:206846c14c80 | 1552 | { |
AzureIoTClient | 28:add19eb7defa | 1553 | result = 0; |
AzureIoTClient | 28:add19eb7defa | 1554 | } |
AzureIoTClient | 28:add19eb7defa | 1555 | else |
AzureIoTClient | 28:add19eb7defa | 1556 | { |
AzureIoTClient | 28:add19eb7defa | 1557 | result = send_disposition(link, message_id, delivery_state); |
AzureIoTClient | 41:0e723f9cbd89 | 1558 | if (result != 0) |
AzureIoTClient | 20:206846c14c80 | 1559 | { |
AzureIoTClient | 20:206846c14c80 | 1560 | LogError("Cannot send disposition frame"); |
AzureIoTClient | 28:add19eb7defa | 1561 | result = __FAILURE__; |
AzureIoTClient | 20:206846c14c80 | 1562 | } |
AzureIoTClient | 20:206846c14c80 | 1563 | } |
AzureIoTClient | 41:0e723f9cbd89 | 1564 | |
AzureIoTClient | 20:206846c14c80 | 1565 | return result; |
AzureIoTClient | 23:1111ee8bcba4 | 1566 | } |
AzureIoTClient | 34:6be9c2058664 | 1567 | |
AzureIoTClient | 34:6be9c2058664 | 1568 | void link_dowork(LINK_HANDLE link) |
AzureIoTClient | 34:6be9c2058664 | 1569 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1570 | if (link == NULL) |
AzureIoTClient | 41:0e723f9cbd89 | 1571 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1572 | LogError("NULL link"); |
AzureIoTClient | 41:0e723f9cbd89 | 1573 | } |
AzureIoTClient | 41:0e723f9cbd89 | 1574 | else |
AzureIoTClient | 34:6be9c2058664 | 1575 | { |
AzureIoTClient | 34:6be9c2058664 | 1576 | tickcounter_ms_t current_tick; |
AzureIoTClient | 34:6be9c2058664 | 1577 | |
AzureIoTClient | 34:6be9c2058664 | 1578 | if (tickcounter_get_current_ms(link->tick_counter, ¤t_tick) != 0) |
AzureIoTClient | 34:6be9c2058664 | 1579 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1580 | LogError("Cannot get tick counter value"); |
AzureIoTClient | 34:6be9c2058664 | 1581 | } |
AzureIoTClient | 34:6be9c2058664 | 1582 | else |
AzureIoTClient | 34:6be9c2058664 | 1583 | { |
AzureIoTClient | 34:6be9c2058664 | 1584 | // go through all and find timed out deliveries |
AzureIoTClient | 34:6be9c2058664 | 1585 | LIST_ITEM_HANDLE item = singlylinkedlist_get_head_item(link->pending_deliveries); |
AzureIoTClient | 34:6be9c2058664 | 1586 | while (item != NULL) |
AzureIoTClient | 34:6be9c2058664 | 1587 | { |
AzureIoTClient | 34:6be9c2058664 | 1588 | LIST_ITEM_HANDLE next_item = singlylinkedlist_get_next_item(item); |
AzureIoTClient | 36:8e1d94b0a70c | 1589 | ASYNC_OPERATION_HANDLE delivery_instance_async_operation = (ASYNC_OPERATION_HANDLE)singlylinkedlist_item_get_value(item); |
AzureIoTClient | 36:8e1d94b0a70c | 1590 | DELIVERY_INSTANCE* delivery_instance = (DELIVERY_INSTANCE*)GET_ASYNC_OPERATION_CONTEXT(DELIVERY_INSTANCE, delivery_instance_async_operation); |
AzureIoTClient | 34:6be9c2058664 | 1591 | |
AzureIoTClient | 34:6be9c2058664 | 1592 | if ((delivery_instance->timeout != 0) && |
AzureIoTClient | 34:6be9c2058664 | 1593 | (current_tick - delivery_instance->start_tick >= delivery_instance->timeout)) |
AzureIoTClient | 34:6be9c2058664 | 1594 | { |
AzureIoTClient | 34:6be9c2058664 | 1595 | if (delivery_instance->on_delivery_settled != NULL) |
AzureIoTClient | 34:6be9c2058664 | 1596 | { |
AzureIoTClient | 34:6be9c2058664 | 1597 | delivery_instance->on_delivery_settled(delivery_instance->callback_context, delivery_instance->delivery_id, LINK_DELIVERY_SETTLE_REASON_TIMEOUT, NULL); |
AzureIoTClient | 34:6be9c2058664 | 1598 | } |
AzureIoTClient | 34:6be9c2058664 | 1599 | |
AzureIoTClient | 41:0e723f9cbd89 | 1600 | if (singlylinkedlist_remove(link->pending_deliveries, item) != 0) |
AzureIoTClient | 41:0e723f9cbd89 | 1601 | { |
AzureIoTClient | 41:0e723f9cbd89 | 1602 | LogError("Cannot remove item from list"); |
AzureIoTClient | 41:0e723f9cbd89 | 1603 | } |
AzureIoTClient | 41:0e723f9cbd89 | 1604 | |
AzureIoTClient | 36:8e1d94b0a70c | 1605 | async_operation_destroy(delivery_instance_async_operation); |
AzureIoTClient | 34:6be9c2058664 | 1606 | } |
AzureIoTClient | 34:6be9c2058664 | 1607 | |
AzureIoTClient | 34:6be9c2058664 | 1608 | item = next_item; |
AzureIoTClient | 34:6be9c2058664 | 1609 | } |
AzureIoTClient | 34:6be9c2058664 | 1610 | } |
AzureIoTClient | 34:6be9c2058664 | 1611 | } |
AzureIoTClient | 34:6be9c2058664 | 1612 | } |
AzureIoTClient | 43:4c1e4e94cdd3 | 1613 | |
AzureIoTClient | 43:4c1e4e94cdd3 | 1614 | ON_LINK_DETACH_EVENT_SUBSCRIPTION_HANDLE link_subscribe_on_link_detach_received(LINK_HANDLE link, ON_LINK_DETACH_RECEIVED on_link_detach_received, void* context) |
AzureIoTClient | 43:4c1e4e94cdd3 | 1615 | { |
AzureIoTClient | 43:4c1e4e94cdd3 | 1616 | ON_LINK_DETACH_EVENT_SUBSCRIPTION_HANDLE result; |
AzureIoTClient | 43:4c1e4e94cdd3 | 1617 | |
AzureIoTClient | 43:4c1e4e94cdd3 | 1618 | if ((link == NULL) || |
AzureIoTClient | 43:4c1e4e94cdd3 | 1619 | (on_link_detach_received == NULL)) |
AzureIoTClient | 43:4c1e4e94cdd3 | 1620 | { |
AzureIoTClient | 43:4c1e4e94cdd3 | 1621 | LogError("Invalid arguments: link = %p, on_link_detach_received = %p, context = %p", |
AzureIoTClient | 43:4c1e4e94cdd3 | 1622 | link, on_link_detach_received, context); |
AzureIoTClient | 43:4c1e4e94cdd3 | 1623 | result = NULL; |
AzureIoTClient | 43:4c1e4e94cdd3 | 1624 | } |
AzureIoTClient | 43:4c1e4e94cdd3 | 1625 | else |
AzureIoTClient | 43:4c1e4e94cdd3 | 1626 | { |
AzureIoTClient | 43:4c1e4e94cdd3 | 1627 | if (link->on_link_detach_received_event_subscription.on_link_detach_received != NULL) |
AzureIoTClient | 43:4c1e4e94cdd3 | 1628 | { |
AzureIoTClient | 43:4c1e4e94cdd3 | 1629 | LogError("Already subscribed for on_link_detach_received events"); |
AzureIoTClient | 43:4c1e4e94cdd3 | 1630 | result = NULL; |
AzureIoTClient | 43:4c1e4e94cdd3 | 1631 | } |
AzureIoTClient | 43:4c1e4e94cdd3 | 1632 | else |
AzureIoTClient | 43:4c1e4e94cdd3 | 1633 | { |
AzureIoTClient | 43:4c1e4e94cdd3 | 1634 | link->on_link_detach_received_event_subscription.on_link_detach_received = on_link_detach_received; |
AzureIoTClient | 43:4c1e4e94cdd3 | 1635 | link->on_link_detach_received_event_subscription.context = context; |
AzureIoTClient | 43:4c1e4e94cdd3 | 1636 | |
AzureIoTClient | 43:4c1e4e94cdd3 | 1637 | result = &link->on_link_detach_received_event_subscription; |
AzureIoTClient | 43:4c1e4e94cdd3 | 1638 | } |
AzureIoTClient | 43:4c1e4e94cdd3 | 1639 | } |
AzureIoTClient | 43:4c1e4e94cdd3 | 1640 | |
AzureIoTClient | 43:4c1e4e94cdd3 | 1641 | return result; |
AzureIoTClient | 43:4c1e4e94cdd3 | 1642 | } |
AzureIoTClient | 43:4c1e4e94cdd3 | 1643 | |
AzureIoTClient | 43:4c1e4e94cdd3 | 1644 | void link_unsubscribe_on_link_detach_received(ON_LINK_DETACH_EVENT_SUBSCRIPTION_HANDLE event_subscription) |
AzureIoTClient | 43:4c1e4e94cdd3 | 1645 | { |
AzureIoTClient | 43:4c1e4e94cdd3 | 1646 | if (event_subscription == NULL) |
AzureIoTClient | 43:4c1e4e94cdd3 | 1647 | { |
AzureIoTClient | 43:4c1e4e94cdd3 | 1648 | LogError("NULL event_subscription"); |
AzureIoTClient | 43:4c1e4e94cdd3 | 1649 | } |
AzureIoTClient | 43:4c1e4e94cdd3 | 1650 | else |
AzureIoTClient | 43:4c1e4e94cdd3 | 1651 | { |
AzureIoTClient | 43:4c1e4e94cdd3 | 1652 | event_subscription->on_link_detach_received = NULL; |
AzureIoTClient | 43:4c1e4e94cdd3 | 1653 | event_subscription->context = NULL; |
AzureIoTClient | 43:4c1e4e94cdd3 | 1654 | } |
AzureIoTClient | 43:4c1e4e94cdd3 | 1655 | } |