Xin Zhang / azure-iot-c-sdk-f767zi

Dependents:   samplemqtt

Committer:
XinZhangMS
Date:
Thu Aug 23 06:52:14 2018 +0000
Revision:
0:f7f1f0d76dd6
azure-c-sdk for mbed os supporting NUCLEO_F767ZI

Who changed what in which revision?

UserRevisionLine numberNew contents of line
XinZhangMS 0:f7f1f0d76dd6 1 // Copyright (c) Microsoft. All rights reserved.
XinZhangMS 0:f7f1f0d76dd6 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
XinZhangMS 0:f7f1f0d76dd6 3
XinZhangMS 0:f7f1f0d76dd6 4 #include <stdlib.h>
XinZhangMS 0:f7f1f0d76dd6 5 #include <string.h>
XinZhangMS 0:f7f1f0d76dd6 6 #include "azure_c_shared_utility/optimize_size.h"
XinZhangMS 0:f7f1f0d76dd6 7 #include "azure_c_shared_utility/gballoc.h"
XinZhangMS 0:f7f1f0d76dd6 8 #include "azure_uamqp_c/session.h"
XinZhangMS 0:f7f1f0d76dd6 9 #include "azure_uamqp_c/connection.h"
XinZhangMS 0:f7f1f0d76dd6 10 #include "azure_uamqp_c/amqp_definitions.h"
XinZhangMS 0:f7f1f0d76dd6 11
XinZhangMS 0:f7f1f0d76dd6 12 typedef enum LINK_ENDPOINT_STATE_TAG
XinZhangMS 0:f7f1f0d76dd6 13 {
XinZhangMS 0:f7f1f0d76dd6 14 LINK_ENDPOINT_STATE_NOT_ATTACHED,
XinZhangMS 0:f7f1f0d76dd6 15 LINK_ENDPOINT_STATE_ATTACHED,
XinZhangMS 0:f7f1f0d76dd6 16 LINK_ENDPOINT_STATE_DETACHING
XinZhangMS 0:f7f1f0d76dd6 17 } LINK_ENDPOINT_STATE;
XinZhangMS 0:f7f1f0d76dd6 18
XinZhangMS 0:f7f1f0d76dd6 19 typedef struct LINK_ENDPOINT_INSTANCE_TAG
XinZhangMS 0:f7f1f0d76dd6 20 {
XinZhangMS 0:f7f1f0d76dd6 21 char* name;
XinZhangMS 0:f7f1f0d76dd6 22 handle input_handle;
XinZhangMS 0:f7f1f0d76dd6 23 handle output_handle;
XinZhangMS 0:f7f1f0d76dd6 24 ON_ENDPOINT_FRAME_RECEIVED frame_received_callback;
XinZhangMS 0:f7f1f0d76dd6 25 ON_SESSION_STATE_CHANGED on_session_state_changed;
XinZhangMS 0:f7f1f0d76dd6 26 ON_SESSION_FLOW_ON on_session_flow_on;
XinZhangMS 0:f7f1f0d76dd6 27 void* callback_context;
XinZhangMS 0:f7f1f0d76dd6 28 SESSION_HANDLE session;
XinZhangMS 0:f7f1f0d76dd6 29 LINK_ENDPOINT_STATE link_endpoint_state;
XinZhangMS 0:f7f1f0d76dd6 30 } LINK_ENDPOINT_INSTANCE;
XinZhangMS 0:f7f1f0d76dd6 31
XinZhangMS 0:f7f1f0d76dd6 32 typedef struct SESSION_INSTANCE_TAG
XinZhangMS 0:f7f1f0d76dd6 33 {
XinZhangMS 0:f7f1f0d76dd6 34 ON_ENDPOINT_FRAME_RECEIVED frame_received_callback;
XinZhangMS 0:f7f1f0d76dd6 35 void* frame_received_callback_context;
XinZhangMS 0:f7f1f0d76dd6 36 SESSION_STATE session_state;
XinZhangMS 0:f7f1f0d76dd6 37 SESSION_STATE previous_session_state;
XinZhangMS 0:f7f1f0d76dd6 38 CONNECTION_HANDLE connection;
XinZhangMS 0:f7f1f0d76dd6 39 ENDPOINT_HANDLE endpoint;
XinZhangMS 0:f7f1f0d76dd6 40 LINK_ENDPOINT_INSTANCE** link_endpoints;
XinZhangMS 0:f7f1f0d76dd6 41 uint32_t link_endpoint_count;
XinZhangMS 0:f7f1f0d76dd6 42
XinZhangMS 0:f7f1f0d76dd6 43 ON_LINK_ATTACHED on_link_attached;
XinZhangMS 0:f7f1f0d76dd6 44 void* on_link_attached_callback_context;
XinZhangMS 0:f7f1f0d76dd6 45
XinZhangMS 0:f7f1f0d76dd6 46 /* Codes_S_R_S_SESSION_01_016: [next-outgoing-id The next-outgoing-id is the transfer-id to assign to the next transfer frame.] */
XinZhangMS 0:f7f1f0d76dd6 47 transfer_number next_outgoing_id;
XinZhangMS 0:f7f1f0d76dd6 48 transfer_number next_incoming_id;
XinZhangMS 0:f7f1f0d76dd6 49 uint32_t desired_incoming_window;
XinZhangMS 0:f7f1f0d76dd6 50 uint32_t incoming_window;
XinZhangMS 0:f7f1f0d76dd6 51 uint32_t outgoing_window;
XinZhangMS 0:f7f1f0d76dd6 52 handle handle_max;
XinZhangMS 0:f7f1f0d76dd6 53 uint32_t remote_incoming_window;
XinZhangMS 0:f7f1f0d76dd6 54 uint32_t remote_outgoing_window;
XinZhangMS 0:f7f1f0d76dd6 55 unsigned int is_underlying_connection_open : 1;
XinZhangMS 0:f7f1f0d76dd6 56 } SESSION_INSTANCE;
XinZhangMS 0:f7f1f0d76dd6 57
XinZhangMS 0:f7f1f0d76dd6 58 #define UNDERLYING_CONNECTION_NOT_OPEN 0
XinZhangMS 0:f7f1f0d76dd6 59 #define UNDERLYING_CONNECTION_OPEN 1
XinZhangMS 0:f7f1f0d76dd6 60
XinZhangMS 0:f7f1f0d76dd6 61 static void remove_link_endpoint(LINK_ENDPOINT_HANDLE link_endpoint)
XinZhangMS 0:f7f1f0d76dd6 62 {
XinZhangMS 0:f7f1f0d76dd6 63 if (link_endpoint != NULL)
XinZhangMS 0:f7f1f0d76dd6 64 {
XinZhangMS 0:f7f1f0d76dd6 65 LINK_ENDPOINT_INSTANCE* endpoint_instance = (LINK_ENDPOINT_INSTANCE*)link_endpoint;
XinZhangMS 0:f7f1f0d76dd6 66 SESSION_INSTANCE* session_instance = endpoint_instance->session;
XinZhangMS 0:f7f1f0d76dd6 67 uint32_t i;
XinZhangMS 0:f7f1f0d76dd6 68
XinZhangMS 0:f7f1f0d76dd6 69 for (i = 0; i < session_instance->link_endpoint_count; i++)
XinZhangMS 0:f7f1f0d76dd6 70 {
XinZhangMS 0:f7f1f0d76dd6 71 if (session_instance->link_endpoints[i] == link_endpoint)
XinZhangMS 0:f7f1f0d76dd6 72 {
XinZhangMS 0:f7f1f0d76dd6 73 break;
XinZhangMS 0:f7f1f0d76dd6 74 }
XinZhangMS 0:f7f1f0d76dd6 75 }
XinZhangMS 0:f7f1f0d76dd6 76
XinZhangMS 0:f7f1f0d76dd6 77 if (i < session_instance->link_endpoint_count)
XinZhangMS 0:f7f1f0d76dd6 78 {
XinZhangMS 0:f7f1f0d76dd6 79 LINK_ENDPOINT_INSTANCE** new_endpoints;
XinZhangMS 0:f7f1f0d76dd6 80
XinZhangMS 0:f7f1f0d76dd6 81 if (i < (session_instance->link_endpoint_count - 1))
XinZhangMS 0:f7f1f0d76dd6 82 {
XinZhangMS 0:f7f1f0d76dd6 83 (void)memmove(&session_instance->link_endpoints[i], &session_instance->link_endpoints[i + 1], (session_instance->link_endpoint_count - (uint32_t)i - 1) * sizeof(LINK_ENDPOINT_INSTANCE*));
XinZhangMS 0:f7f1f0d76dd6 84 }
XinZhangMS 0:f7f1f0d76dd6 85
XinZhangMS 0:f7f1f0d76dd6 86 session_instance->link_endpoint_count--;
XinZhangMS 0:f7f1f0d76dd6 87
XinZhangMS 0:f7f1f0d76dd6 88 if (session_instance->link_endpoint_count == 0)
XinZhangMS 0:f7f1f0d76dd6 89 {
XinZhangMS 0:f7f1f0d76dd6 90 free(session_instance->link_endpoints);
XinZhangMS 0:f7f1f0d76dd6 91 session_instance->link_endpoints = NULL;
XinZhangMS 0:f7f1f0d76dd6 92 }
XinZhangMS 0:f7f1f0d76dd6 93 else
XinZhangMS 0:f7f1f0d76dd6 94 {
XinZhangMS 0:f7f1f0d76dd6 95 new_endpoints = (LINK_ENDPOINT_INSTANCE**)realloc(session_instance->link_endpoints, sizeof(LINK_ENDPOINT_INSTANCE*) * session_instance->link_endpoint_count);
XinZhangMS 0:f7f1f0d76dd6 96 if (new_endpoints != NULL)
XinZhangMS 0:f7f1f0d76dd6 97 {
XinZhangMS 0:f7f1f0d76dd6 98 session_instance->link_endpoints = new_endpoints;
XinZhangMS 0:f7f1f0d76dd6 99 }
XinZhangMS 0:f7f1f0d76dd6 100 }
XinZhangMS 0:f7f1f0d76dd6 101 }
XinZhangMS 0:f7f1f0d76dd6 102 }
XinZhangMS 0:f7f1f0d76dd6 103 }
XinZhangMS 0:f7f1f0d76dd6 104
XinZhangMS 0:f7f1f0d76dd6 105 static void free_link_endpoint(LINK_ENDPOINT_HANDLE link_endpoint)
XinZhangMS 0:f7f1f0d76dd6 106 {
XinZhangMS 0:f7f1f0d76dd6 107 if (link_endpoint->name != NULL)
XinZhangMS 0:f7f1f0d76dd6 108 {
XinZhangMS 0:f7f1f0d76dd6 109 free(link_endpoint->name);
XinZhangMS 0:f7f1f0d76dd6 110 }
XinZhangMS 0:f7f1f0d76dd6 111
XinZhangMS 0:f7f1f0d76dd6 112 free(link_endpoint);
XinZhangMS 0:f7f1f0d76dd6 113 }
XinZhangMS 0:f7f1f0d76dd6 114
XinZhangMS 0:f7f1f0d76dd6 115 static void session_set_state(SESSION_INSTANCE* session_instance, SESSION_STATE session_state)
XinZhangMS 0:f7f1f0d76dd6 116 {
XinZhangMS 0:f7f1f0d76dd6 117 uint32_t i;
XinZhangMS 0:f7f1f0d76dd6 118
XinZhangMS 0:f7f1f0d76dd6 119 session_instance->previous_session_state = session_instance->session_state;
XinZhangMS 0:f7f1f0d76dd6 120 session_instance->session_state = session_state;
XinZhangMS 0:f7f1f0d76dd6 121
XinZhangMS 0:f7f1f0d76dd6 122 for (i = 0; i < session_instance->link_endpoint_count; i++)
XinZhangMS 0:f7f1f0d76dd6 123 {
XinZhangMS 0:f7f1f0d76dd6 124 if (session_instance->link_endpoints[i]->on_session_state_changed != NULL)
XinZhangMS 0:f7f1f0d76dd6 125 {
XinZhangMS 0:f7f1f0d76dd6 126 if (session_instance->link_endpoints[i]->link_endpoint_state != LINK_ENDPOINT_STATE_DETACHING)
XinZhangMS 0:f7f1f0d76dd6 127 {
XinZhangMS 0:f7f1f0d76dd6 128 session_instance->link_endpoints[i]->on_session_state_changed(session_instance->link_endpoints[i]->callback_context, session_state, session_instance->previous_session_state);
XinZhangMS 0:f7f1f0d76dd6 129 }
XinZhangMS 0:f7f1f0d76dd6 130 }
XinZhangMS 0:f7f1f0d76dd6 131 }
XinZhangMS 0:f7f1f0d76dd6 132 }
XinZhangMS 0:f7f1f0d76dd6 133
XinZhangMS 0:f7f1f0d76dd6 134 static int send_end_frame(SESSION_INSTANCE* session_instance, ERROR_HANDLE error_handle)
XinZhangMS 0:f7f1f0d76dd6 135 {
XinZhangMS 0:f7f1f0d76dd6 136 int result;
XinZhangMS 0:f7f1f0d76dd6 137 END_HANDLE end_performative;
XinZhangMS 0:f7f1f0d76dd6 138
XinZhangMS 0:f7f1f0d76dd6 139 end_performative = end_create();
XinZhangMS 0:f7f1f0d76dd6 140 if (end_performative == NULL)
XinZhangMS 0:f7f1f0d76dd6 141 {
XinZhangMS 0:f7f1f0d76dd6 142 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 143 }
XinZhangMS 0:f7f1f0d76dd6 144 else
XinZhangMS 0:f7f1f0d76dd6 145 {
XinZhangMS 0:f7f1f0d76dd6 146 if ((error_handle != NULL) &&
XinZhangMS 0:f7f1f0d76dd6 147 (end_set_error(end_performative, error_handle) != 0))
XinZhangMS 0:f7f1f0d76dd6 148 {
XinZhangMS 0:f7f1f0d76dd6 149 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 150 }
XinZhangMS 0:f7f1f0d76dd6 151 else
XinZhangMS 0:f7f1f0d76dd6 152 {
XinZhangMS 0:f7f1f0d76dd6 153 AMQP_VALUE end_performative_value = amqpvalue_create_end(end_performative);
XinZhangMS 0:f7f1f0d76dd6 154 if (end_performative_value == NULL)
XinZhangMS 0:f7f1f0d76dd6 155 {
XinZhangMS 0:f7f1f0d76dd6 156 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 157 }
XinZhangMS 0:f7f1f0d76dd6 158 else
XinZhangMS 0:f7f1f0d76dd6 159 {
XinZhangMS 0:f7f1f0d76dd6 160 if (connection_encode_frame(session_instance->endpoint, end_performative_value, NULL, 0, NULL, NULL) != 0)
XinZhangMS 0:f7f1f0d76dd6 161 {
XinZhangMS 0:f7f1f0d76dd6 162 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 163 }
XinZhangMS 0:f7f1f0d76dd6 164 else
XinZhangMS 0:f7f1f0d76dd6 165 {
XinZhangMS 0:f7f1f0d76dd6 166 result = 0;
XinZhangMS 0:f7f1f0d76dd6 167 }
XinZhangMS 0:f7f1f0d76dd6 168
XinZhangMS 0:f7f1f0d76dd6 169 amqpvalue_destroy(end_performative_value);
XinZhangMS 0:f7f1f0d76dd6 170 }
XinZhangMS 0:f7f1f0d76dd6 171 }
XinZhangMS 0:f7f1f0d76dd6 172
XinZhangMS 0:f7f1f0d76dd6 173 end_destroy(end_performative);
XinZhangMS 0:f7f1f0d76dd6 174 }
XinZhangMS 0:f7f1f0d76dd6 175
XinZhangMS 0:f7f1f0d76dd6 176 return result;
XinZhangMS 0:f7f1f0d76dd6 177 }
XinZhangMS 0:f7f1f0d76dd6 178
XinZhangMS 0:f7f1f0d76dd6 179 static void end_session_with_error(SESSION_INSTANCE* session_instance, const char* condition_value, const char* description)
XinZhangMS 0:f7f1f0d76dd6 180 {
XinZhangMS 0:f7f1f0d76dd6 181 ERROR_HANDLE error_handle = error_create(condition_value);
XinZhangMS 0:f7f1f0d76dd6 182 if (error_handle == NULL)
XinZhangMS 0:f7f1f0d76dd6 183 {
XinZhangMS 0:f7f1f0d76dd6 184 /* fatal error */
XinZhangMS 0:f7f1f0d76dd6 185 session_set_state(session_instance, SESSION_STATE_DISCARDING);
XinZhangMS 0:f7f1f0d76dd6 186 (void)connection_close(session_instance->connection, "amqp:internal-error", "Cannot allocate error handle to end session", NULL);
XinZhangMS 0:f7f1f0d76dd6 187 }
XinZhangMS 0:f7f1f0d76dd6 188 else
XinZhangMS 0:f7f1f0d76dd6 189 {
XinZhangMS 0:f7f1f0d76dd6 190 if ((error_set_description(error_handle, description) != 0) ||
XinZhangMS 0:f7f1f0d76dd6 191 (send_end_frame(session_instance, error_handle) != 0))
XinZhangMS 0:f7f1f0d76dd6 192 {
XinZhangMS 0:f7f1f0d76dd6 193 /* fatal error */
XinZhangMS 0:f7f1f0d76dd6 194 session_set_state(session_instance, SESSION_STATE_DISCARDING);
XinZhangMS 0:f7f1f0d76dd6 195 (void)connection_close(session_instance->connection, "amqp:internal-error", "Cannot allocate error handle to end session", NULL);
XinZhangMS 0:f7f1f0d76dd6 196 }
XinZhangMS 0:f7f1f0d76dd6 197 else
XinZhangMS 0:f7f1f0d76dd6 198 {
XinZhangMS 0:f7f1f0d76dd6 199 session_set_state(session_instance, SESSION_STATE_DISCARDING);
XinZhangMS 0:f7f1f0d76dd6 200 }
XinZhangMS 0:f7f1f0d76dd6 201
XinZhangMS 0:f7f1f0d76dd6 202 error_destroy(error_handle);
XinZhangMS 0:f7f1f0d76dd6 203 }
XinZhangMS 0:f7f1f0d76dd6 204 }
XinZhangMS 0:f7f1f0d76dd6 205
XinZhangMS 0:f7f1f0d76dd6 206 static int send_begin(SESSION_INSTANCE* session_instance)
XinZhangMS 0:f7f1f0d76dd6 207 {
XinZhangMS 0:f7f1f0d76dd6 208 int result;
XinZhangMS 0:f7f1f0d76dd6 209 BEGIN_HANDLE begin = begin_create(session_instance->next_outgoing_id, session_instance->incoming_window, session_instance->outgoing_window);
XinZhangMS 0:f7f1f0d76dd6 210
XinZhangMS 0:f7f1f0d76dd6 211 if (begin == NULL)
XinZhangMS 0:f7f1f0d76dd6 212 {
XinZhangMS 0:f7f1f0d76dd6 213 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 214 }
XinZhangMS 0:f7f1f0d76dd6 215 else
XinZhangMS 0:f7f1f0d76dd6 216 {
XinZhangMS 0:f7f1f0d76dd6 217 uint16_t remote_channel;
XinZhangMS 0:f7f1f0d76dd6 218 if (begin_set_handle_max(begin, session_instance->handle_max) != 0)
XinZhangMS 0:f7f1f0d76dd6 219 {
XinZhangMS 0:f7f1f0d76dd6 220 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 221 }
XinZhangMS 0:f7f1f0d76dd6 222 else if ((session_instance->session_state == SESSION_STATE_BEGIN_RCVD) &&
XinZhangMS 0:f7f1f0d76dd6 223 ((connection_endpoint_get_incoming_channel(session_instance->endpoint, &remote_channel) != 0) ||
XinZhangMS 0:f7f1f0d76dd6 224 (begin_set_remote_channel(begin, remote_channel) != 0)))
XinZhangMS 0:f7f1f0d76dd6 225 {
XinZhangMS 0:f7f1f0d76dd6 226 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 227 }
XinZhangMS 0:f7f1f0d76dd6 228 else
XinZhangMS 0:f7f1f0d76dd6 229 {
XinZhangMS 0:f7f1f0d76dd6 230 AMQP_VALUE begin_performative_value = amqpvalue_create_begin(begin);
XinZhangMS 0:f7f1f0d76dd6 231 if (begin_performative_value == NULL)
XinZhangMS 0:f7f1f0d76dd6 232 {
XinZhangMS 0:f7f1f0d76dd6 233 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 234 }
XinZhangMS 0:f7f1f0d76dd6 235 else
XinZhangMS 0:f7f1f0d76dd6 236 {
XinZhangMS 0:f7f1f0d76dd6 237 if (connection_encode_frame(session_instance->endpoint, begin_performative_value, NULL, 0, NULL, NULL) != 0)
XinZhangMS 0:f7f1f0d76dd6 238 {
XinZhangMS 0:f7f1f0d76dd6 239 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 240 }
XinZhangMS 0:f7f1f0d76dd6 241 else
XinZhangMS 0:f7f1f0d76dd6 242 {
XinZhangMS 0:f7f1f0d76dd6 243 result = 0;
XinZhangMS 0:f7f1f0d76dd6 244 }
XinZhangMS 0:f7f1f0d76dd6 245
XinZhangMS 0:f7f1f0d76dd6 246 amqpvalue_destroy(begin_performative_value);
XinZhangMS 0:f7f1f0d76dd6 247 }
XinZhangMS 0:f7f1f0d76dd6 248 }
XinZhangMS 0:f7f1f0d76dd6 249
XinZhangMS 0:f7f1f0d76dd6 250 begin_destroy(begin);
XinZhangMS 0:f7f1f0d76dd6 251 }
XinZhangMS 0:f7f1f0d76dd6 252
XinZhangMS 0:f7f1f0d76dd6 253 return result;
XinZhangMS 0:f7f1f0d76dd6 254 }
XinZhangMS 0:f7f1f0d76dd6 255
XinZhangMS 0:f7f1f0d76dd6 256 static int send_flow(SESSION_INSTANCE* session)
XinZhangMS 0:f7f1f0d76dd6 257 {
XinZhangMS 0:f7f1f0d76dd6 258 int result;
XinZhangMS 0:f7f1f0d76dd6 259 if (session == NULL)
XinZhangMS 0:f7f1f0d76dd6 260 {
XinZhangMS 0:f7f1f0d76dd6 261 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 262 }
XinZhangMS 0:f7f1f0d76dd6 263 else
XinZhangMS 0:f7f1f0d76dd6 264 {
XinZhangMS 0:f7f1f0d76dd6 265 FLOW_HANDLE flow = flow_create(session->incoming_window, session->next_outgoing_id, session->outgoing_window);
XinZhangMS 0:f7f1f0d76dd6 266
XinZhangMS 0:f7f1f0d76dd6 267 if (flow == NULL)
XinZhangMS 0:f7f1f0d76dd6 268 {
XinZhangMS 0:f7f1f0d76dd6 269 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 270 }
XinZhangMS 0:f7f1f0d76dd6 271 else
XinZhangMS 0:f7f1f0d76dd6 272 {
XinZhangMS 0:f7f1f0d76dd6 273 if (flow_set_next_incoming_id(flow, session->next_incoming_id) != 0)
XinZhangMS 0:f7f1f0d76dd6 274 {
XinZhangMS 0:f7f1f0d76dd6 275 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 276 }
XinZhangMS 0:f7f1f0d76dd6 277 else
XinZhangMS 0:f7f1f0d76dd6 278 {
XinZhangMS 0:f7f1f0d76dd6 279 AMQP_VALUE flow_performative_value = amqpvalue_create_flow(flow);
XinZhangMS 0:f7f1f0d76dd6 280 if (flow_performative_value == NULL)
XinZhangMS 0:f7f1f0d76dd6 281 {
XinZhangMS 0:f7f1f0d76dd6 282 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 283 }
XinZhangMS 0:f7f1f0d76dd6 284 else
XinZhangMS 0:f7f1f0d76dd6 285 {
XinZhangMS 0:f7f1f0d76dd6 286 if (connection_encode_frame(session->endpoint, flow_performative_value, NULL, 0, NULL, NULL) != 0)
XinZhangMS 0:f7f1f0d76dd6 287 {
XinZhangMS 0:f7f1f0d76dd6 288 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 289 }
XinZhangMS 0:f7f1f0d76dd6 290 else
XinZhangMS 0:f7f1f0d76dd6 291 {
XinZhangMS 0:f7f1f0d76dd6 292 result = 0;
XinZhangMS 0:f7f1f0d76dd6 293 }
XinZhangMS 0:f7f1f0d76dd6 294
XinZhangMS 0:f7f1f0d76dd6 295 amqpvalue_destroy(flow_performative_value);
XinZhangMS 0:f7f1f0d76dd6 296 }
XinZhangMS 0:f7f1f0d76dd6 297 }
XinZhangMS 0:f7f1f0d76dd6 298
XinZhangMS 0:f7f1f0d76dd6 299 flow_destroy(flow);
XinZhangMS 0:f7f1f0d76dd6 300 }
XinZhangMS 0:f7f1f0d76dd6 301 }
XinZhangMS 0:f7f1f0d76dd6 302
XinZhangMS 0:f7f1f0d76dd6 303 return result;
XinZhangMS 0:f7f1f0d76dd6 304 }
XinZhangMS 0:f7f1f0d76dd6 305
XinZhangMS 0:f7f1f0d76dd6 306 static LINK_ENDPOINT_INSTANCE* find_link_endpoint_by_name(SESSION_INSTANCE* session, const char* name)
XinZhangMS 0:f7f1f0d76dd6 307 {
XinZhangMS 0:f7f1f0d76dd6 308 uint32_t i;
XinZhangMS 0:f7f1f0d76dd6 309 LINK_ENDPOINT_INSTANCE* result;
XinZhangMS 0:f7f1f0d76dd6 310
XinZhangMS 0:f7f1f0d76dd6 311 for (i = 0; i < session->link_endpoint_count; i++)
XinZhangMS 0:f7f1f0d76dd6 312 {
XinZhangMS 0:f7f1f0d76dd6 313 if (strcmp(session->link_endpoints[i]->name, name) == 0)
XinZhangMS 0:f7f1f0d76dd6 314 {
XinZhangMS 0:f7f1f0d76dd6 315 break;
XinZhangMS 0:f7f1f0d76dd6 316 }
XinZhangMS 0:f7f1f0d76dd6 317 }
XinZhangMS 0:f7f1f0d76dd6 318
XinZhangMS 0:f7f1f0d76dd6 319 if (i == session->link_endpoint_count)
XinZhangMS 0:f7f1f0d76dd6 320 {
XinZhangMS 0:f7f1f0d76dd6 321 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 322 }
XinZhangMS 0:f7f1f0d76dd6 323 else
XinZhangMS 0:f7f1f0d76dd6 324 {
XinZhangMS 0:f7f1f0d76dd6 325 result = session->link_endpoints[i];
XinZhangMS 0:f7f1f0d76dd6 326 }
XinZhangMS 0:f7f1f0d76dd6 327
XinZhangMS 0:f7f1f0d76dd6 328 return result;
XinZhangMS 0:f7f1f0d76dd6 329 }
XinZhangMS 0:f7f1f0d76dd6 330
XinZhangMS 0:f7f1f0d76dd6 331 static LINK_ENDPOINT_INSTANCE* find_link_endpoint_by_input_handle(SESSION_INSTANCE* session, handle input_handle)
XinZhangMS 0:f7f1f0d76dd6 332 {
XinZhangMS 0:f7f1f0d76dd6 333 uint32_t i;
XinZhangMS 0:f7f1f0d76dd6 334 LINK_ENDPOINT_INSTANCE* result;
XinZhangMS 0:f7f1f0d76dd6 335
XinZhangMS 0:f7f1f0d76dd6 336 for (i = 0; i < session->link_endpoint_count; i++)
XinZhangMS 0:f7f1f0d76dd6 337 {
XinZhangMS 0:f7f1f0d76dd6 338 if (session->link_endpoints[i]->input_handle == input_handle)
XinZhangMS 0:f7f1f0d76dd6 339 {
XinZhangMS 0:f7f1f0d76dd6 340 break;
XinZhangMS 0:f7f1f0d76dd6 341 }
XinZhangMS 0:f7f1f0d76dd6 342 }
XinZhangMS 0:f7f1f0d76dd6 343
XinZhangMS 0:f7f1f0d76dd6 344 if (i == session->link_endpoint_count)
XinZhangMS 0:f7f1f0d76dd6 345 {
XinZhangMS 0:f7f1f0d76dd6 346 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 347 }
XinZhangMS 0:f7f1f0d76dd6 348 else
XinZhangMS 0:f7f1f0d76dd6 349 {
XinZhangMS 0:f7f1f0d76dd6 350 result = session->link_endpoints[i];
XinZhangMS 0:f7f1f0d76dd6 351 }
XinZhangMS 0:f7f1f0d76dd6 352
XinZhangMS 0:f7f1f0d76dd6 353 return result;
XinZhangMS 0:f7f1f0d76dd6 354 }
XinZhangMS 0:f7f1f0d76dd6 355
XinZhangMS 0:f7f1f0d76dd6 356 static void on_connection_state_changed(void* context, CONNECTION_STATE new_connection_state, CONNECTION_STATE previous_connection_state)
XinZhangMS 0:f7f1f0d76dd6 357 {
XinZhangMS 0:f7f1f0d76dd6 358 SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)context;
XinZhangMS 0:f7f1f0d76dd6 359
XinZhangMS 0:f7f1f0d76dd6 360 /* Codes_S_R_S_SESSION_01_060: [If the previous connection state is not OPENED and the new connection state is OPENED, the BEGIN frame shall be sent out and the state shall be switched to BEGIN_SENT.] */
XinZhangMS 0:f7f1f0d76dd6 361 if ((new_connection_state == CONNECTION_STATE_OPENED) && (previous_connection_state != CONNECTION_STATE_OPENED) && (session_instance->session_state == SESSION_STATE_UNMAPPED))
XinZhangMS 0:f7f1f0d76dd6 362 {
XinZhangMS 0:f7f1f0d76dd6 363 if (send_begin(session_instance) == 0)
XinZhangMS 0:f7f1f0d76dd6 364 {
XinZhangMS 0:f7f1f0d76dd6 365 session_set_state(session_instance, SESSION_STATE_BEGIN_SENT);
XinZhangMS 0:f7f1f0d76dd6 366 }
XinZhangMS 0:f7f1f0d76dd6 367 }
XinZhangMS 0:f7f1f0d76dd6 368 /* Codes_S_R_S_SESSION_01_061: [If the previous connection state is OPENED and the new connection state is not OPENED anymore, the state shall be switched to DISCARDING.] */
XinZhangMS 0:f7f1f0d76dd6 369 else if ((new_connection_state == CONNECTION_STATE_CLOSE_RCVD) || (new_connection_state == CONNECTION_STATE_END))
XinZhangMS 0:f7f1f0d76dd6 370 {
XinZhangMS 0:f7f1f0d76dd6 371 session_set_state(session_instance, SESSION_STATE_DISCARDING);
XinZhangMS 0:f7f1f0d76dd6 372 }
XinZhangMS 0:f7f1f0d76dd6 373 /* Codes_S_R_S_SESSION_09_001: [If the new connection state is ERROR, the state shall be switched to ERROR.] */
XinZhangMS 0:f7f1f0d76dd6 374 else if (new_connection_state == CONNECTION_STATE_ERROR)
XinZhangMS 0:f7f1f0d76dd6 375 {
XinZhangMS 0:f7f1f0d76dd6 376 session_set_state(session_instance, SESSION_STATE_ERROR);
XinZhangMS 0:f7f1f0d76dd6 377 }
XinZhangMS 0:f7f1f0d76dd6 378 }
XinZhangMS 0:f7f1f0d76dd6 379
XinZhangMS 0:f7f1f0d76dd6 380 static void on_frame_received(void* context, AMQP_VALUE performative, uint32_t payload_size, const unsigned char* payload_bytes)
XinZhangMS 0:f7f1f0d76dd6 381 {
XinZhangMS 0:f7f1f0d76dd6 382 SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)context;
XinZhangMS 0:f7f1f0d76dd6 383 AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(performative);
XinZhangMS 0:f7f1f0d76dd6 384
XinZhangMS 0:f7f1f0d76dd6 385 if (is_begin_type_by_descriptor(descriptor))
XinZhangMS 0:f7f1f0d76dd6 386 {
XinZhangMS 0:f7f1f0d76dd6 387 BEGIN_HANDLE begin_handle;
XinZhangMS 0:f7f1f0d76dd6 388
XinZhangMS 0:f7f1f0d76dd6 389 if (amqpvalue_get_begin(performative, &begin_handle) != 0)
XinZhangMS 0:f7f1f0d76dd6 390 {
XinZhangMS 0:f7f1f0d76dd6 391 connection_close(session_instance->connection, "amqp:decode-error", "Cannot decode BEGIN frame", NULL);
XinZhangMS 0:f7f1f0d76dd6 392 }
XinZhangMS 0:f7f1f0d76dd6 393 else
XinZhangMS 0:f7f1f0d76dd6 394 {
XinZhangMS 0:f7f1f0d76dd6 395 if ((begin_get_incoming_window(begin_handle, &session_instance->remote_incoming_window) != 0) ||
XinZhangMS 0:f7f1f0d76dd6 396 (begin_get_next_outgoing_id(begin_handle, &session_instance->next_incoming_id) != 0))
XinZhangMS 0:f7f1f0d76dd6 397 {
XinZhangMS 0:f7f1f0d76dd6 398 /* error */
XinZhangMS 0:f7f1f0d76dd6 399 begin_destroy(begin_handle);
XinZhangMS 0:f7f1f0d76dd6 400 session_set_state(session_instance, SESSION_STATE_DISCARDING);
XinZhangMS 0:f7f1f0d76dd6 401 connection_close(session_instance->connection, "amqp:decode-error", "Cannot get incoming windows and next outgoing id", NULL);
XinZhangMS 0:f7f1f0d76dd6 402 }
XinZhangMS 0:f7f1f0d76dd6 403 else
XinZhangMS 0:f7f1f0d76dd6 404 {
XinZhangMS 0:f7f1f0d76dd6 405 begin_destroy(begin_handle);
XinZhangMS 0:f7f1f0d76dd6 406
XinZhangMS 0:f7f1f0d76dd6 407 if (session_instance->session_state == SESSION_STATE_BEGIN_SENT)
XinZhangMS 0:f7f1f0d76dd6 408 {
XinZhangMS 0:f7f1f0d76dd6 409 session_set_state(session_instance, SESSION_STATE_MAPPED);
XinZhangMS 0:f7f1f0d76dd6 410 }
XinZhangMS 0:f7f1f0d76dd6 411 else if(session_instance->session_state == SESSION_STATE_UNMAPPED)
XinZhangMS 0:f7f1f0d76dd6 412 {
XinZhangMS 0:f7f1f0d76dd6 413 session_set_state(session_instance, SESSION_STATE_BEGIN_RCVD);
XinZhangMS 0:f7f1f0d76dd6 414 if (send_begin(session_instance) != 0)
XinZhangMS 0:f7f1f0d76dd6 415 {
XinZhangMS 0:f7f1f0d76dd6 416 connection_close(session_instance->connection, "amqp:internal-error", "Failed sending BEGIN frame", NULL);
XinZhangMS 0:f7f1f0d76dd6 417 session_set_state(session_instance, SESSION_STATE_DISCARDING);
XinZhangMS 0:f7f1f0d76dd6 418 }
XinZhangMS 0:f7f1f0d76dd6 419 else
XinZhangMS 0:f7f1f0d76dd6 420 {
XinZhangMS 0:f7f1f0d76dd6 421 session_set_state(session_instance, SESSION_STATE_MAPPED);
XinZhangMS 0:f7f1f0d76dd6 422 }
XinZhangMS 0:f7f1f0d76dd6 423 }
XinZhangMS 0:f7f1f0d76dd6 424 }
XinZhangMS 0:f7f1f0d76dd6 425 }
XinZhangMS 0:f7f1f0d76dd6 426 }
XinZhangMS 0:f7f1f0d76dd6 427 else if (is_attach_type_by_descriptor(descriptor))
XinZhangMS 0:f7f1f0d76dd6 428 {
XinZhangMS 0:f7f1f0d76dd6 429 const char* name = NULL;
XinZhangMS 0:f7f1f0d76dd6 430 ATTACH_HANDLE attach_handle;
XinZhangMS 0:f7f1f0d76dd6 431
XinZhangMS 0:f7f1f0d76dd6 432 if (amqpvalue_get_attach(performative, &attach_handle) != 0)
XinZhangMS 0:f7f1f0d76dd6 433 {
XinZhangMS 0:f7f1f0d76dd6 434 end_session_with_error(session_instance, "amqp:decode-error", "Cannot decode ATTACH frame");
XinZhangMS 0:f7f1f0d76dd6 435 }
XinZhangMS 0:f7f1f0d76dd6 436 else
XinZhangMS 0:f7f1f0d76dd6 437 {
XinZhangMS 0:f7f1f0d76dd6 438 role role;
XinZhangMS 0:f7f1f0d76dd6 439 AMQP_VALUE source;
XinZhangMS 0:f7f1f0d76dd6 440 AMQP_VALUE target;
XinZhangMS 0:f7f1f0d76dd6 441
XinZhangMS 0:f7f1f0d76dd6 442 if (attach_get_name(attach_handle, &name) != 0)
XinZhangMS 0:f7f1f0d76dd6 443 {
XinZhangMS 0:f7f1f0d76dd6 444 end_session_with_error(session_instance, "amqp:decode-error", "Cannot get link name from ATTACH frame");
XinZhangMS 0:f7f1f0d76dd6 445 }
XinZhangMS 0:f7f1f0d76dd6 446 else if (attach_get_role(attach_handle, &role) != 0)
XinZhangMS 0:f7f1f0d76dd6 447 {
XinZhangMS 0:f7f1f0d76dd6 448 end_session_with_error(session_instance, "amqp:decode-error", "Cannot get link role from ATTACH frame");
XinZhangMS 0:f7f1f0d76dd6 449 }
XinZhangMS 0:f7f1f0d76dd6 450 else
XinZhangMS 0:f7f1f0d76dd6 451 {
XinZhangMS 0:f7f1f0d76dd6 452 LINK_ENDPOINT_INSTANCE* link_endpoint;
XinZhangMS 0:f7f1f0d76dd6 453
XinZhangMS 0:f7f1f0d76dd6 454 if (attach_get_source(attach_handle, &source) != 0)
XinZhangMS 0:f7f1f0d76dd6 455 {
XinZhangMS 0:f7f1f0d76dd6 456 source = NULL;
XinZhangMS 0:f7f1f0d76dd6 457 }
XinZhangMS 0:f7f1f0d76dd6 458 if (attach_get_target(attach_handle, &target) != 0)
XinZhangMS 0:f7f1f0d76dd6 459 {
XinZhangMS 0:f7f1f0d76dd6 460 target = NULL;
XinZhangMS 0:f7f1f0d76dd6 461 }
XinZhangMS 0:f7f1f0d76dd6 462
XinZhangMS 0:f7f1f0d76dd6 463 link_endpoint = find_link_endpoint_by_name(session_instance, name);
XinZhangMS 0:f7f1f0d76dd6 464 if (link_endpoint == NULL)
XinZhangMS 0:f7f1f0d76dd6 465 {
XinZhangMS 0:f7f1f0d76dd6 466 /* new link attach */
XinZhangMS 0:f7f1f0d76dd6 467 if (session_instance->on_link_attached != NULL)
XinZhangMS 0:f7f1f0d76dd6 468 {
XinZhangMS 0:f7f1f0d76dd6 469 LINK_ENDPOINT_HANDLE new_link_endpoint = session_create_link_endpoint(session_instance, name);
XinZhangMS 0:f7f1f0d76dd6 470 if (new_link_endpoint == NULL)
XinZhangMS 0:f7f1f0d76dd6 471 {
XinZhangMS 0:f7f1f0d76dd6 472 end_session_with_error(session_instance, "amqp:internal-error", "Cannot create link endpoint");
XinZhangMS 0:f7f1f0d76dd6 473 }
XinZhangMS 0:f7f1f0d76dd6 474 else if (attach_get_handle(attach_handle, &new_link_endpoint->input_handle) != 0)
XinZhangMS 0:f7f1f0d76dd6 475 {
XinZhangMS 0:f7f1f0d76dd6 476 end_session_with_error(session_instance, "amqp:decode-error", "Cannot get input handle from ATTACH frame");
XinZhangMS 0:f7f1f0d76dd6 477 }
XinZhangMS 0:f7f1f0d76dd6 478 else
XinZhangMS 0:f7f1f0d76dd6 479 {
XinZhangMS 0:f7f1f0d76dd6 480 new_link_endpoint->link_endpoint_state = LINK_ENDPOINT_STATE_ATTACHED;
XinZhangMS 0:f7f1f0d76dd6 481
XinZhangMS 0:f7f1f0d76dd6 482 if (!session_instance->on_link_attached(session_instance->on_link_attached_callback_context, new_link_endpoint, name, role, source, target))
XinZhangMS 0:f7f1f0d76dd6 483 {
XinZhangMS 0:f7f1f0d76dd6 484 remove_link_endpoint(new_link_endpoint);
XinZhangMS 0:f7f1f0d76dd6 485 free_link_endpoint(new_link_endpoint);
XinZhangMS 0:f7f1f0d76dd6 486 new_link_endpoint = NULL;
XinZhangMS 0:f7f1f0d76dd6 487 }
XinZhangMS 0:f7f1f0d76dd6 488 else
XinZhangMS 0:f7f1f0d76dd6 489 {
XinZhangMS 0:f7f1f0d76dd6 490 if (new_link_endpoint->frame_received_callback != NULL)
XinZhangMS 0:f7f1f0d76dd6 491 {
XinZhangMS 0:f7f1f0d76dd6 492 new_link_endpoint->frame_received_callback(new_link_endpoint->callback_context, performative, payload_size, payload_bytes);
XinZhangMS 0:f7f1f0d76dd6 493 }
XinZhangMS 0:f7f1f0d76dd6 494 }
XinZhangMS 0:f7f1f0d76dd6 495 }
XinZhangMS 0:f7f1f0d76dd6 496 }
XinZhangMS 0:f7f1f0d76dd6 497 }
XinZhangMS 0:f7f1f0d76dd6 498 else
XinZhangMS 0:f7f1f0d76dd6 499 {
XinZhangMS 0:f7f1f0d76dd6 500 if (attach_get_handle(attach_handle, &link_endpoint->input_handle) != 0)
XinZhangMS 0:f7f1f0d76dd6 501 {
XinZhangMS 0:f7f1f0d76dd6 502 end_session_with_error(session_instance, "amqp:decode-error", "Cannot get input handle from ATTACH frame");
XinZhangMS 0:f7f1f0d76dd6 503 }
XinZhangMS 0:f7f1f0d76dd6 504 else
XinZhangMS 0:f7f1f0d76dd6 505 {
XinZhangMS 0:f7f1f0d76dd6 506 link_endpoint->link_endpoint_state = LINK_ENDPOINT_STATE_ATTACHED;
XinZhangMS 0:f7f1f0d76dd6 507
XinZhangMS 0:f7f1f0d76dd6 508 link_endpoint->frame_received_callback(link_endpoint->callback_context, performative, payload_size, payload_bytes);
XinZhangMS 0:f7f1f0d76dd6 509 }
XinZhangMS 0:f7f1f0d76dd6 510 }
XinZhangMS 0:f7f1f0d76dd6 511 }
XinZhangMS 0:f7f1f0d76dd6 512
XinZhangMS 0:f7f1f0d76dd6 513 attach_destroy(attach_handle);
XinZhangMS 0:f7f1f0d76dd6 514 }
XinZhangMS 0:f7f1f0d76dd6 515 }
XinZhangMS 0:f7f1f0d76dd6 516 else if (is_detach_type_by_descriptor(descriptor))
XinZhangMS 0:f7f1f0d76dd6 517 {
XinZhangMS 0:f7f1f0d76dd6 518 DETACH_HANDLE detach_handle;
XinZhangMS 0:f7f1f0d76dd6 519
XinZhangMS 0:f7f1f0d76dd6 520 if (amqpvalue_get_detach(performative, &detach_handle) != 0)
XinZhangMS 0:f7f1f0d76dd6 521 {
XinZhangMS 0:f7f1f0d76dd6 522 end_session_with_error(session_instance, "amqp:decode-error", "Cannot decode DETACH frame");
XinZhangMS 0:f7f1f0d76dd6 523 }
XinZhangMS 0:f7f1f0d76dd6 524 else
XinZhangMS 0:f7f1f0d76dd6 525 {
XinZhangMS 0:f7f1f0d76dd6 526 uint32_t remote_handle;
XinZhangMS 0:f7f1f0d76dd6 527 if (detach_get_handle(detach_handle, &remote_handle) != 0)
XinZhangMS 0:f7f1f0d76dd6 528 {
XinZhangMS 0:f7f1f0d76dd6 529 end_session_with_error(session_instance, "amqp:decode-error", "Cannot get handle from DETACH frame");
XinZhangMS 0:f7f1f0d76dd6 530
XinZhangMS 0:f7f1f0d76dd6 531 detach_destroy(detach_handle);
XinZhangMS 0:f7f1f0d76dd6 532 }
XinZhangMS 0:f7f1f0d76dd6 533 else
XinZhangMS 0:f7f1f0d76dd6 534 {
XinZhangMS 0:f7f1f0d76dd6 535 LINK_ENDPOINT_INSTANCE* link_endpoint;
XinZhangMS 0:f7f1f0d76dd6 536 detach_destroy(detach_handle);
XinZhangMS 0:f7f1f0d76dd6 537
XinZhangMS 0:f7f1f0d76dd6 538 link_endpoint = find_link_endpoint_by_input_handle(session_instance, remote_handle);
XinZhangMS 0:f7f1f0d76dd6 539 if (link_endpoint == NULL)
XinZhangMS 0:f7f1f0d76dd6 540 {
XinZhangMS 0:f7f1f0d76dd6 541 end_session_with_error(session_instance, "amqp:session:unattached-handle", "");
XinZhangMS 0:f7f1f0d76dd6 542 }
XinZhangMS 0:f7f1f0d76dd6 543 else
XinZhangMS 0:f7f1f0d76dd6 544 {
XinZhangMS 0:f7f1f0d76dd6 545 if (link_endpoint->link_endpoint_state != LINK_ENDPOINT_STATE_DETACHING)
XinZhangMS 0:f7f1f0d76dd6 546 {
XinZhangMS 0:f7f1f0d76dd6 547 link_endpoint->link_endpoint_state = LINK_ENDPOINT_STATE_DETACHING;
XinZhangMS 0:f7f1f0d76dd6 548 link_endpoint->frame_received_callback(link_endpoint->callback_context, performative, payload_size, payload_bytes);
XinZhangMS 0:f7f1f0d76dd6 549 }
XinZhangMS 0:f7f1f0d76dd6 550 else
XinZhangMS 0:f7f1f0d76dd6 551 {
XinZhangMS 0:f7f1f0d76dd6 552 /* remove the link endpoint */
XinZhangMS 0:f7f1f0d76dd6 553 remove_link_endpoint(link_endpoint);
XinZhangMS 0:f7f1f0d76dd6 554 free_link_endpoint(link_endpoint);
XinZhangMS 0:f7f1f0d76dd6 555 }
XinZhangMS 0:f7f1f0d76dd6 556 }
XinZhangMS 0:f7f1f0d76dd6 557 }
XinZhangMS 0:f7f1f0d76dd6 558 }
XinZhangMS 0:f7f1f0d76dd6 559 }
XinZhangMS 0:f7f1f0d76dd6 560 else if (is_flow_type_by_descriptor(descriptor))
XinZhangMS 0:f7f1f0d76dd6 561 {
XinZhangMS 0:f7f1f0d76dd6 562 FLOW_HANDLE flow_handle;
XinZhangMS 0:f7f1f0d76dd6 563
XinZhangMS 0:f7f1f0d76dd6 564 if (amqpvalue_get_flow(performative, &flow_handle) != 0)
XinZhangMS 0:f7f1f0d76dd6 565 {
XinZhangMS 0:f7f1f0d76dd6 566 end_session_with_error(session_instance, "amqp:decode-error", "Cannot decode FLOW frame");
XinZhangMS 0:f7f1f0d76dd6 567 }
XinZhangMS 0:f7f1f0d76dd6 568 else
XinZhangMS 0:f7f1f0d76dd6 569 {
XinZhangMS 0:f7f1f0d76dd6 570 uint32_t remote_handle;
XinZhangMS 0:f7f1f0d76dd6 571 transfer_number flow_next_incoming_id;
XinZhangMS 0:f7f1f0d76dd6 572 uint32_t flow_incoming_window;
XinZhangMS 0:f7f1f0d76dd6 573
XinZhangMS 0:f7f1f0d76dd6 574 if (flow_get_next_incoming_id(flow_handle, &flow_next_incoming_id) != 0)
XinZhangMS 0:f7f1f0d76dd6 575 {
XinZhangMS 0:f7f1f0d76dd6 576 /*
XinZhangMS 0:f7f1f0d76dd6 577 If the next-incoming-id field of the flow frame is not set,
XinZhangMS 0:f7f1f0d76dd6 578 then remote-incomingwindow is computed as follows:
XinZhangMS 0:f7f1f0d76dd6 579 initial-outgoing-id(endpoint) + incoming-window(flow) - next-outgoing-id(endpoint)
XinZhangMS 0:f7f1f0d76dd6 580 */
XinZhangMS 0:f7f1f0d76dd6 581 flow_next_incoming_id = session_instance->next_outgoing_id;
XinZhangMS 0:f7f1f0d76dd6 582 }
XinZhangMS 0:f7f1f0d76dd6 583
XinZhangMS 0:f7f1f0d76dd6 584 if ((flow_get_next_outgoing_id(flow_handle, &session_instance->next_incoming_id) != 0) ||
XinZhangMS 0:f7f1f0d76dd6 585 (flow_get_incoming_window(flow_handle, &flow_incoming_window) != 0))
XinZhangMS 0:f7f1f0d76dd6 586 {
XinZhangMS 0:f7f1f0d76dd6 587 flow_destroy(flow_handle);
XinZhangMS 0:f7f1f0d76dd6 588
XinZhangMS 0:f7f1f0d76dd6 589 end_session_with_error(session_instance, "amqp:decode-error", "Cannot decode FLOW frame");
XinZhangMS 0:f7f1f0d76dd6 590 }
XinZhangMS 0:f7f1f0d76dd6 591 else
XinZhangMS 0:f7f1f0d76dd6 592 {
XinZhangMS 0:f7f1f0d76dd6 593 LINK_ENDPOINT_INSTANCE* link_endpoint_instance = NULL;
XinZhangMS 0:f7f1f0d76dd6 594 size_t i;
XinZhangMS 0:f7f1f0d76dd6 595
XinZhangMS 0:f7f1f0d76dd6 596 session_instance->remote_incoming_window = flow_next_incoming_id + flow_incoming_window - session_instance->next_outgoing_id;
XinZhangMS 0:f7f1f0d76dd6 597
XinZhangMS 0:f7f1f0d76dd6 598 if (flow_get_handle(flow_handle, &remote_handle) == 0)
XinZhangMS 0:f7f1f0d76dd6 599 {
XinZhangMS 0:f7f1f0d76dd6 600 link_endpoint_instance = find_link_endpoint_by_input_handle(session_instance, remote_handle);
XinZhangMS 0:f7f1f0d76dd6 601 }
XinZhangMS 0:f7f1f0d76dd6 602
XinZhangMS 0:f7f1f0d76dd6 603 flow_destroy(flow_handle);
XinZhangMS 0:f7f1f0d76dd6 604
XinZhangMS 0:f7f1f0d76dd6 605 if (link_endpoint_instance != NULL)
XinZhangMS 0:f7f1f0d76dd6 606 {
XinZhangMS 0:f7f1f0d76dd6 607 if (link_endpoint_instance->link_endpoint_state != LINK_ENDPOINT_STATE_DETACHING)
XinZhangMS 0:f7f1f0d76dd6 608 {
XinZhangMS 0:f7f1f0d76dd6 609 link_endpoint_instance->frame_received_callback(link_endpoint_instance->callback_context, performative, payload_size, payload_bytes);
XinZhangMS 0:f7f1f0d76dd6 610 }
XinZhangMS 0:f7f1f0d76dd6 611 }
XinZhangMS 0:f7f1f0d76dd6 612
XinZhangMS 0:f7f1f0d76dd6 613 i = 0;
XinZhangMS 0:f7f1f0d76dd6 614 while ((session_instance->remote_incoming_window > 0) && (i < session_instance->link_endpoint_count))
XinZhangMS 0:f7f1f0d76dd6 615 {
XinZhangMS 0:f7f1f0d76dd6 616 /* notify the caller that it can send here */
XinZhangMS 0:f7f1f0d76dd6 617 if (session_instance->link_endpoints[i]->on_session_flow_on != NULL)
XinZhangMS 0:f7f1f0d76dd6 618 {
XinZhangMS 0:f7f1f0d76dd6 619 session_instance->link_endpoints[i]->on_session_flow_on(session_instance->link_endpoints[i]->callback_context);
XinZhangMS 0:f7f1f0d76dd6 620 }
XinZhangMS 0:f7f1f0d76dd6 621
XinZhangMS 0:f7f1f0d76dd6 622 i++;
XinZhangMS 0:f7f1f0d76dd6 623 }
XinZhangMS 0:f7f1f0d76dd6 624 }
XinZhangMS 0:f7f1f0d76dd6 625 }
XinZhangMS 0:f7f1f0d76dd6 626 }
XinZhangMS 0:f7f1f0d76dd6 627 else if (is_transfer_type_by_descriptor(descriptor))
XinZhangMS 0:f7f1f0d76dd6 628 {
XinZhangMS 0:f7f1f0d76dd6 629 TRANSFER_HANDLE transfer_handle;
XinZhangMS 0:f7f1f0d76dd6 630
XinZhangMS 0:f7f1f0d76dd6 631 if (amqpvalue_get_transfer(performative, &transfer_handle) != 0)
XinZhangMS 0:f7f1f0d76dd6 632 {
XinZhangMS 0:f7f1f0d76dd6 633 end_session_with_error(session_instance, "amqp:decode-error", "Cannot decode TRANSFER frame");
XinZhangMS 0:f7f1f0d76dd6 634 }
XinZhangMS 0:f7f1f0d76dd6 635 else
XinZhangMS 0:f7f1f0d76dd6 636 {
XinZhangMS 0:f7f1f0d76dd6 637 uint32_t remote_handle;
XinZhangMS 0:f7f1f0d76dd6 638 delivery_number delivery_id;
XinZhangMS 0:f7f1f0d76dd6 639
XinZhangMS 0:f7f1f0d76dd6 640 transfer_get_delivery_id(transfer_handle, &delivery_id);
XinZhangMS 0:f7f1f0d76dd6 641 if (transfer_get_handle(transfer_handle, &remote_handle) != 0)
XinZhangMS 0:f7f1f0d76dd6 642 {
XinZhangMS 0:f7f1f0d76dd6 643 transfer_destroy(transfer_handle);
XinZhangMS 0:f7f1f0d76dd6 644 end_session_with_error(session_instance, "amqp:decode-error", "Cannot get handle from TRANSFER frame");
XinZhangMS 0:f7f1f0d76dd6 645 }
XinZhangMS 0:f7f1f0d76dd6 646 else
XinZhangMS 0:f7f1f0d76dd6 647 {
XinZhangMS 0:f7f1f0d76dd6 648 LINK_ENDPOINT_INSTANCE* link_endpoint;
XinZhangMS 0:f7f1f0d76dd6 649 transfer_destroy(transfer_handle);
XinZhangMS 0:f7f1f0d76dd6 650
XinZhangMS 0:f7f1f0d76dd6 651 session_instance->next_incoming_id++;
XinZhangMS 0:f7f1f0d76dd6 652 session_instance->remote_outgoing_window--;
XinZhangMS 0:f7f1f0d76dd6 653 session_instance->incoming_window--;
XinZhangMS 0:f7f1f0d76dd6 654
XinZhangMS 0:f7f1f0d76dd6 655 link_endpoint = find_link_endpoint_by_input_handle(session_instance, remote_handle);
XinZhangMS 0:f7f1f0d76dd6 656 if (link_endpoint == NULL)
XinZhangMS 0:f7f1f0d76dd6 657 {
XinZhangMS 0:f7f1f0d76dd6 658 end_session_with_error(session_instance, "amqp:session:unattached-handle", "");
XinZhangMS 0:f7f1f0d76dd6 659 }
XinZhangMS 0:f7f1f0d76dd6 660 else
XinZhangMS 0:f7f1f0d76dd6 661 {
XinZhangMS 0:f7f1f0d76dd6 662 if (link_endpoint->link_endpoint_state != LINK_ENDPOINT_STATE_DETACHING)
XinZhangMS 0:f7f1f0d76dd6 663 {
XinZhangMS 0:f7f1f0d76dd6 664 link_endpoint->frame_received_callback(link_endpoint->callback_context, performative, payload_size, payload_bytes);
XinZhangMS 0:f7f1f0d76dd6 665 }
XinZhangMS 0:f7f1f0d76dd6 666 }
XinZhangMS 0:f7f1f0d76dd6 667
XinZhangMS 0:f7f1f0d76dd6 668 if (session_instance->incoming_window == 0)
XinZhangMS 0:f7f1f0d76dd6 669 {
XinZhangMS 0:f7f1f0d76dd6 670 session_instance->incoming_window = session_instance->desired_incoming_window;
XinZhangMS 0:f7f1f0d76dd6 671 send_flow(session_instance);
XinZhangMS 0:f7f1f0d76dd6 672 }
XinZhangMS 0:f7f1f0d76dd6 673 }
XinZhangMS 0:f7f1f0d76dd6 674 }
XinZhangMS 0:f7f1f0d76dd6 675 }
XinZhangMS 0:f7f1f0d76dd6 676 else if (is_disposition_type_by_descriptor(descriptor))
XinZhangMS 0:f7f1f0d76dd6 677 {
XinZhangMS 0:f7f1f0d76dd6 678 uint32_t i;
XinZhangMS 0:f7f1f0d76dd6 679
XinZhangMS 0:f7f1f0d76dd6 680 for (i = 0; i < session_instance->link_endpoint_count; i++)
XinZhangMS 0:f7f1f0d76dd6 681 {
XinZhangMS 0:f7f1f0d76dd6 682 LINK_ENDPOINT_INSTANCE* link_endpoint = session_instance->link_endpoints[i];
XinZhangMS 0:f7f1f0d76dd6 683 if (link_endpoint->link_endpoint_state != LINK_ENDPOINT_STATE_DETACHING)
XinZhangMS 0:f7f1f0d76dd6 684 {
XinZhangMS 0:f7f1f0d76dd6 685 link_endpoint->frame_received_callback(link_endpoint->callback_context, performative, payload_size, payload_bytes);
XinZhangMS 0:f7f1f0d76dd6 686 }
XinZhangMS 0:f7f1f0d76dd6 687 }
XinZhangMS 0:f7f1f0d76dd6 688 }
XinZhangMS 0:f7f1f0d76dd6 689 else if (is_end_type_by_descriptor(descriptor))
XinZhangMS 0:f7f1f0d76dd6 690 {
XinZhangMS 0:f7f1f0d76dd6 691 END_HANDLE end_handle;
XinZhangMS 0:f7f1f0d76dd6 692
XinZhangMS 0:f7f1f0d76dd6 693 if (amqpvalue_get_end(performative, &end_handle) != 0)
XinZhangMS 0:f7f1f0d76dd6 694 {
XinZhangMS 0:f7f1f0d76dd6 695 end_session_with_error(session_instance, "amqp:decode-error", "Cannot decode END frame");
XinZhangMS 0:f7f1f0d76dd6 696 }
XinZhangMS 0:f7f1f0d76dd6 697 else
XinZhangMS 0:f7f1f0d76dd6 698 {
XinZhangMS 0:f7f1f0d76dd6 699 end_destroy(end_handle);
XinZhangMS 0:f7f1f0d76dd6 700 if ((session_instance->session_state != SESSION_STATE_END_RCVD) &&
XinZhangMS 0:f7f1f0d76dd6 701 (session_instance->session_state != SESSION_STATE_DISCARDING))
XinZhangMS 0:f7f1f0d76dd6 702 {
XinZhangMS 0:f7f1f0d76dd6 703 session_set_state(session_instance, SESSION_STATE_END_RCVD);
XinZhangMS 0:f7f1f0d76dd6 704 if (send_end_frame(session_instance, NULL) != 0)
XinZhangMS 0:f7f1f0d76dd6 705 {
XinZhangMS 0:f7f1f0d76dd6 706 /* fatal error */
XinZhangMS 0:f7f1f0d76dd6 707 (void)connection_close(session_instance->connection, "amqp:internal-error", "Cannot send END frame.", NULL);
XinZhangMS 0:f7f1f0d76dd6 708 }
XinZhangMS 0:f7f1f0d76dd6 709
XinZhangMS 0:f7f1f0d76dd6 710 session_set_state(session_instance, SESSION_STATE_DISCARDING);
XinZhangMS 0:f7f1f0d76dd6 711 }
XinZhangMS 0:f7f1f0d76dd6 712 }
XinZhangMS 0:f7f1f0d76dd6 713 }
XinZhangMS 0:f7f1f0d76dd6 714 }
XinZhangMS 0:f7f1f0d76dd6 715
XinZhangMS 0:f7f1f0d76dd6 716 SESSION_HANDLE session_create(CONNECTION_HANDLE connection, ON_LINK_ATTACHED on_link_attached, void* callback_context)
XinZhangMS 0:f7f1f0d76dd6 717 {
XinZhangMS 0:f7f1f0d76dd6 718 SESSION_INSTANCE* result;
XinZhangMS 0:f7f1f0d76dd6 719
XinZhangMS 0:f7f1f0d76dd6 720 if (connection == NULL)
XinZhangMS 0:f7f1f0d76dd6 721 {
XinZhangMS 0:f7f1f0d76dd6 722 /* Codes_S_R_S_SESSION_01_031: [If connection is NULL, session_create shall fail and return NULL.] */
XinZhangMS 0:f7f1f0d76dd6 723 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 724 }
XinZhangMS 0:f7f1f0d76dd6 725 else
XinZhangMS 0:f7f1f0d76dd6 726 {
XinZhangMS 0:f7f1f0d76dd6 727 /* Codes_S_R_S_SESSION_01_030: [session_create shall create a new session instance and return a non-NULL handle to it.] */
XinZhangMS 0:f7f1f0d76dd6 728 result = (SESSION_INSTANCE*)malloc(sizeof(SESSION_INSTANCE));
XinZhangMS 0:f7f1f0d76dd6 729 /* Codes_S_R_S_SESSION_01_042: [If allocating memory for the session fails, session_create shall fail and return NULL.] */
XinZhangMS 0:f7f1f0d76dd6 730 if (result != NULL)
XinZhangMS 0:f7f1f0d76dd6 731 {
XinZhangMS 0:f7f1f0d76dd6 732 result->connection = connection;
XinZhangMS 0:f7f1f0d76dd6 733 result->link_endpoints = NULL;
XinZhangMS 0:f7f1f0d76dd6 734 result->link_endpoint_count = 0;
XinZhangMS 0:f7f1f0d76dd6 735 result->handle_max = 4294967295u;
XinZhangMS 0:f7f1f0d76dd6 736
XinZhangMS 0:f7f1f0d76dd6 737 /* Codes_S_R_S_SESSION_01_057: [The delivery ids shall be assigned starting at 0.] */
XinZhangMS 0:f7f1f0d76dd6 738 /* Codes_S_R_S_SESSION_01_017: [The nextoutgoing-id MAY be initialized to an arbitrary value ] */
XinZhangMS 0:f7f1f0d76dd6 739 result->next_outgoing_id = 0;
XinZhangMS 0:f7f1f0d76dd6 740
XinZhangMS 0:f7f1f0d76dd6 741 result->desired_incoming_window = 1;
XinZhangMS 0:f7f1f0d76dd6 742 result->incoming_window = 1;
XinZhangMS 0:f7f1f0d76dd6 743 result->outgoing_window = 1;
XinZhangMS 0:f7f1f0d76dd6 744 result->handle_max = 4294967295u;
XinZhangMS 0:f7f1f0d76dd6 745 result->remote_incoming_window = 0;
XinZhangMS 0:f7f1f0d76dd6 746 result->remote_outgoing_window = 0;
XinZhangMS 0:f7f1f0d76dd6 747 result->previous_session_state = SESSION_STATE_UNMAPPED;
XinZhangMS 0:f7f1f0d76dd6 748 result->is_underlying_connection_open = UNDERLYING_CONNECTION_NOT_OPEN;
XinZhangMS 0:f7f1f0d76dd6 749 result->session_state = SESSION_STATE_UNMAPPED;
XinZhangMS 0:f7f1f0d76dd6 750 result->on_link_attached = on_link_attached;
XinZhangMS 0:f7f1f0d76dd6 751 result->on_link_attached_callback_context = callback_context;
XinZhangMS 0:f7f1f0d76dd6 752
XinZhangMS 0:f7f1f0d76dd6 753 /* Codes_S_R_S_SESSION_01_032: [session_create shall create a new session endpoint by calling connection_create_endpoint.] */
XinZhangMS 0:f7f1f0d76dd6 754 result->endpoint = connection_create_endpoint(connection);
XinZhangMS 0:f7f1f0d76dd6 755 if (result->endpoint == NULL)
XinZhangMS 0:f7f1f0d76dd6 756 {
XinZhangMS 0:f7f1f0d76dd6 757 /* Codes_S_R_S_SESSION_01_033: [If connection_create_endpoint fails, session_create shall fail and return NULL.] */
XinZhangMS 0:f7f1f0d76dd6 758 free(result);
XinZhangMS 0:f7f1f0d76dd6 759 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 760 }
XinZhangMS 0:f7f1f0d76dd6 761 else
XinZhangMS 0:f7f1f0d76dd6 762 {
XinZhangMS 0:f7f1f0d76dd6 763 session_set_state(result, SESSION_STATE_UNMAPPED);
XinZhangMS 0:f7f1f0d76dd6 764 }
XinZhangMS 0:f7f1f0d76dd6 765 }
XinZhangMS 0:f7f1f0d76dd6 766 }
XinZhangMS 0:f7f1f0d76dd6 767
XinZhangMS 0:f7f1f0d76dd6 768 return result;
XinZhangMS 0:f7f1f0d76dd6 769 }
XinZhangMS 0:f7f1f0d76dd6 770
XinZhangMS 0:f7f1f0d76dd6 771 SESSION_HANDLE session_create_from_endpoint(CONNECTION_HANDLE connection, ENDPOINT_HANDLE endpoint, ON_LINK_ATTACHED on_link_attached, void* callback_context)
XinZhangMS 0:f7f1f0d76dd6 772 {
XinZhangMS 0:f7f1f0d76dd6 773 SESSION_INSTANCE* result;
XinZhangMS 0:f7f1f0d76dd6 774
XinZhangMS 0:f7f1f0d76dd6 775 if (endpoint == NULL)
XinZhangMS 0:f7f1f0d76dd6 776 {
XinZhangMS 0:f7f1f0d76dd6 777 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 778 }
XinZhangMS 0:f7f1f0d76dd6 779 else
XinZhangMS 0:f7f1f0d76dd6 780 {
XinZhangMS 0:f7f1f0d76dd6 781 result = (SESSION_INSTANCE*)malloc(sizeof(SESSION_INSTANCE));
XinZhangMS 0:f7f1f0d76dd6 782 if (result != NULL)
XinZhangMS 0:f7f1f0d76dd6 783 {
XinZhangMS 0:f7f1f0d76dd6 784 result->connection = connection;
XinZhangMS 0:f7f1f0d76dd6 785 result->link_endpoints = NULL;
XinZhangMS 0:f7f1f0d76dd6 786 result->link_endpoint_count = 0;
XinZhangMS 0:f7f1f0d76dd6 787 result->handle_max = 4294967295u;
XinZhangMS 0:f7f1f0d76dd6 788
XinZhangMS 0:f7f1f0d76dd6 789 result->next_outgoing_id = 0;
XinZhangMS 0:f7f1f0d76dd6 790
XinZhangMS 0:f7f1f0d76dd6 791 result->desired_incoming_window = 1;
XinZhangMS 0:f7f1f0d76dd6 792 result->incoming_window = 1;
XinZhangMS 0:f7f1f0d76dd6 793 result->outgoing_window = 1;
XinZhangMS 0:f7f1f0d76dd6 794 result->handle_max = 4294967295u;
XinZhangMS 0:f7f1f0d76dd6 795 result->remote_incoming_window = 0;
XinZhangMS 0:f7f1f0d76dd6 796 result->remote_outgoing_window = 0;
XinZhangMS 0:f7f1f0d76dd6 797 result->previous_session_state = SESSION_STATE_UNMAPPED;
XinZhangMS 0:f7f1f0d76dd6 798 result->is_underlying_connection_open = UNDERLYING_CONNECTION_NOT_OPEN;
XinZhangMS 0:f7f1f0d76dd6 799 result->session_state = SESSION_STATE_UNMAPPED;
XinZhangMS 0:f7f1f0d76dd6 800 result->on_link_attached = on_link_attached;
XinZhangMS 0:f7f1f0d76dd6 801 result->on_link_attached_callback_context = callback_context;
XinZhangMS 0:f7f1f0d76dd6 802
XinZhangMS 0:f7f1f0d76dd6 803 result->endpoint = endpoint;
XinZhangMS 0:f7f1f0d76dd6 804 session_set_state(result, SESSION_STATE_UNMAPPED);
XinZhangMS 0:f7f1f0d76dd6 805 }
XinZhangMS 0:f7f1f0d76dd6 806 }
XinZhangMS 0:f7f1f0d76dd6 807
XinZhangMS 0:f7f1f0d76dd6 808 return result;
XinZhangMS 0:f7f1f0d76dd6 809 }
XinZhangMS 0:f7f1f0d76dd6 810
XinZhangMS 0:f7f1f0d76dd6 811 void session_destroy(SESSION_HANDLE session)
XinZhangMS 0:f7f1f0d76dd6 812 {
XinZhangMS 0:f7f1f0d76dd6 813 /* Codes_S_R_S_SESSION_01_036: [If session is NULL, session_destroy shall do nothing.] */
XinZhangMS 0:f7f1f0d76dd6 814 if (session != NULL)
XinZhangMS 0:f7f1f0d76dd6 815 {
XinZhangMS 0:f7f1f0d76dd6 816 SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)session;
XinZhangMS 0:f7f1f0d76dd6 817
XinZhangMS 0:f7f1f0d76dd6 818 session_end(session, NULL, NULL);
XinZhangMS 0:f7f1f0d76dd6 819
XinZhangMS 0:f7f1f0d76dd6 820 /* Codes_S_R_S_SESSION_01_034: [session_destroy shall free all resources allocated by session_create.] */
XinZhangMS 0:f7f1f0d76dd6 821 /* Codes_S_R_S_SESSION_01_035: [The endpoint created in session_create shall be freed by calling connection_destroy_endpoint.] */
XinZhangMS 0:f7f1f0d76dd6 822 connection_destroy_endpoint(session_instance->endpoint);
XinZhangMS 0:f7f1f0d76dd6 823 if (session_instance->link_endpoints != NULL)
XinZhangMS 0:f7f1f0d76dd6 824 {
XinZhangMS 0:f7f1f0d76dd6 825 free(session_instance->link_endpoints);
XinZhangMS 0:f7f1f0d76dd6 826 }
XinZhangMS 0:f7f1f0d76dd6 827
XinZhangMS 0:f7f1f0d76dd6 828 free(session);
XinZhangMS 0:f7f1f0d76dd6 829 }
XinZhangMS 0:f7f1f0d76dd6 830 }
XinZhangMS 0:f7f1f0d76dd6 831
XinZhangMS 0:f7f1f0d76dd6 832 int session_begin(SESSION_HANDLE session)
XinZhangMS 0:f7f1f0d76dd6 833 {
XinZhangMS 0:f7f1f0d76dd6 834 int result;
XinZhangMS 0:f7f1f0d76dd6 835
XinZhangMS 0:f7f1f0d76dd6 836 if (session == NULL)
XinZhangMS 0:f7f1f0d76dd6 837 {
XinZhangMS 0:f7f1f0d76dd6 838 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 839 }
XinZhangMS 0:f7f1f0d76dd6 840 else
XinZhangMS 0:f7f1f0d76dd6 841 {
XinZhangMS 0:f7f1f0d76dd6 842 SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)session;
XinZhangMS 0:f7f1f0d76dd6 843
XinZhangMS 0:f7f1f0d76dd6 844 if (connection_start_endpoint(session_instance->endpoint, on_frame_received, on_connection_state_changed, session_instance) != 0)
XinZhangMS 0:f7f1f0d76dd6 845 {
XinZhangMS 0:f7f1f0d76dd6 846 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 847 }
XinZhangMS 0:f7f1f0d76dd6 848 else
XinZhangMS 0:f7f1f0d76dd6 849 {
XinZhangMS 0:f7f1f0d76dd6 850 if (!session_instance->is_underlying_connection_open)
XinZhangMS 0:f7f1f0d76dd6 851 {
XinZhangMS 0:f7f1f0d76dd6 852 if (connection_open(session_instance->connection) != 0)
XinZhangMS 0:f7f1f0d76dd6 853 {
XinZhangMS 0:f7f1f0d76dd6 854 session_instance->is_underlying_connection_open = UNDERLYING_CONNECTION_NOT_OPEN;
XinZhangMS 0:f7f1f0d76dd6 855 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 856 }
XinZhangMS 0:f7f1f0d76dd6 857 else
XinZhangMS 0:f7f1f0d76dd6 858 {
XinZhangMS 0:f7f1f0d76dd6 859 session_instance->is_underlying_connection_open = UNDERLYING_CONNECTION_OPEN;
XinZhangMS 0:f7f1f0d76dd6 860 result = 0;
XinZhangMS 0:f7f1f0d76dd6 861 }
XinZhangMS 0:f7f1f0d76dd6 862 }
XinZhangMS 0:f7f1f0d76dd6 863 else
XinZhangMS 0:f7f1f0d76dd6 864 {
XinZhangMS 0:f7f1f0d76dd6 865 result = 0;
XinZhangMS 0:f7f1f0d76dd6 866 }
XinZhangMS 0:f7f1f0d76dd6 867 }
XinZhangMS 0:f7f1f0d76dd6 868 }
XinZhangMS 0:f7f1f0d76dd6 869
XinZhangMS 0:f7f1f0d76dd6 870 return result;
XinZhangMS 0:f7f1f0d76dd6 871 }
XinZhangMS 0:f7f1f0d76dd6 872
XinZhangMS 0:f7f1f0d76dd6 873 int session_end(SESSION_HANDLE session, const char* condition_value, const char* description)
XinZhangMS 0:f7f1f0d76dd6 874 {
XinZhangMS 0:f7f1f0d76dd6 875 int result;
XinZhangMS 0:f7f1f0d76dd6 876
XinZhangMS 0:f7f1f0d76dd6 877 if (session == NULL)
XinZhangMS 0:f7f1f0d76dd6 878 {
XinZhangMS 0:f7f1f0d76dd6 879 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 880 }
XinZhangMS 0:f7f1f0d76dd6 881 else
XinZhangMS 0:f7f1f0d76dd6 882 {
XinZhangMS 0:f7f1f0d76dd6 883 SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)session;
XinZhangMS 0:f7f1f0d76dd6 884 size_t i;
XinZhangMS 0:f7f1f0d76dd6 885
XinZhangMS 0:f7f1f0d76dd6 886 if ((session_instance->session_state != SESSION_STATE_UNMAPPED) &&
XinZhangMS 0:f7f1f0d76dd6 887 (session_instance->session_state != SESSION_STATE_DISCARDING))
XinZhangMS 0:f7f1f0d76dd6 888 {
XinZhangMS 0:f7f1f0d76dd6 889 ERROR_HANDLE error_handle = NULL;
XinZhangMS 0:f7f1f0d76dd6 890 result = 0;
XinZhangMS 0:f7f1f0d76dd6 891
XinZhangMS 0:f7f1f0d76dd6 892 if (condition_value != NULL)
XinZhangMS 0:f7f1f0d76dd6 893 {
XinZhangMS 0:f7f1f0d76dd6 894 error_handle = error_create(condition_value);
XinZhangMS 0:f7f1f0d76dd6 895 if (error_handle == NULL)
XinZhangMS 0:f7f1f0d76dd6 896 {
XinZhangMS 0:f7f1f0d76dd6 897 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 898 }
XinZhangMS 0:f7f1f0d76dd6 899 else
XinZhangMS 0:f7f1f0d76dd6 900 {
XinZhangMS 0:f7f1f0d76dd6 901 if (error_set_description(error_handle, description) != 0)
XinZhangMS 0:f7f1f0d76dd6 902 {
XinZhangMS 0:f7f1f0d76dd6 903 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 904 }
XinZhangMS 0:f7f1f0d76dd6 905 }
XinZhangMS 0:f7f1f0d76dd6 906 }
XinZhangMS 0:f7f1f0d76dd6 907
XinZhangMS 0:f7f1f0d76dd6 908 if (result == 0)
XinZhangMS 0:f7f1f0d76dd6 909 {
XinZhangMS 0:f7f1f0d76dd6 910 if (send_end_frame(session_instance, error_handle) != 0)
XinZhangMS 0:f7f1f0d76dd6 911 {
XinZhangMS 0:f7f1f0d76dd6 912 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 913 }
XinZhangMS 0:f7f1f0d76dd6 914 else
XinZhangMS 0:f7f1f0d76dd6 915 {
XinZhangMS 0:f7f1f0d76dd6 916 session_set_state(session_instance, SESSION_STATE_DISCARDING);
XinZhangMS 0:f7f1f0d76dd6 917 result = 0;
XinZhangMS 0:f7f1f0d76dd6 918 }
XinZhangMS 0:f7f1f0d76dd6 919 }
XinZhangMS 0:f7f1f0d76dd6 920
XinZhangMS 0:f7f1f0d76dd6 921 if (error_handle != NULL)
XinZhangMS 0:f7f1f0d76dd6 922 {
XinZhangMS 0:f7f1f0d76dd6 923 error_destroy(error_handle);
XinZhangMS 0:f7f1f0d76dd6 924 }
XinZhangMS 0:f7f1f0d76dd6 925 }
XinZhangMS 0:f7f1f0d76dd6 926 else
XinZhangMS 0:f7f1f0d76dd6 927 {
XinZhangMS 0:f7f1f0d76dd6 928 result = 0;
XinZhangMS 0:f7f1f0d76dd6 929 }
XinZhangMS 0:f7f1f0d76dd6 930
XinZhangMS 0:f7f1f0d76dd6 931 // all link endpoints are destroyed when the session end happens
XinZhangMS 0:f7f1f0d76dd6 932 for (i = 0; i < session_instance->link_endpoint_count; i++)
XinZhangMS 0:f7f1f0d76dd6 933 {
XinZhangMS 0:f7f1f0d76dd6 934 free_link_endpoint(session_instance->link_endpoints[i]);
XinZhangMS 0:f7f1f0d76dd6 935 }
XinZhangMS 0:f7f1f0d76dd6 936
XinZhangMS 0:f7f1f0d76dd6 937 session_instance->link_endpoint_count = 0;
XinZhangMS 0:f7f1f0d76dd6 938 }
XinZhangMS 0:f7f1f0d76dd6 939
XinZhangMS 0:f7f1f0d76dd6 940 return result;
XinZhangMS 0:f7f1f0d76dd6 941 }
XinZhangMS 0:f7f1f0d76dd6 942
XinZhangMS 0:f7f1f0d76dd6 943 int session_set_incoming_window(SESSION_HANDLE session, uint32_t incoming_window)
XinZhangMS 0:f7f1f0d76dd6 944 {
XinZhangMS 0:f7f1f0d76dd6 945 int result;
XinZhangMS 0:f7f1f0d76dd6 946
XinZhangMS 0:f7f1f0d76dd6 947 if (session == NULL)
XinZhangMS 0:f7f1f0d76dd6 948 {
XinZhangMS 0:f7f1f0d76dd6 949 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 950 }
XinZhangMS 0:f7f1f0d76dd6 951 else
XinZhangMS 0:f7f1f0d76dd6 952 {
XinZhangMS 0:f7f1f0d76dd6 953 SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)session;
XinZhangMS 0:f7f1f0d76dd6 954
XinZhangMS 0:f7f1f0d76dd6 955 session_instance->desired_incoming_window = incoming_window;
XinZhangMS 0:f7f1f0d76dd6 956 session_instance->incoming_window = incoming_window;
XinZhangMS 0:f7f1f0d76dd6 957
XinZhangMS 0:f7f1f0d76dd6 958 result = 0;
XinZhangMS 0:f7f1f0d76dd6 959 }
XinZhangMS 0:f7f1f0d76dd6 960
XinZhangMS 0:f7f1f0d76dd6 961 return result;
XinZhangMS 0:f7f1f0d76dd6 962 }
XinZhangMS 0:f7f1f0d76dd6 963
XinZhangMS 0:f7f1f0d76dd6 964 int session_get_incoming_window(SESSION_HANDLE session, uint32_t* incoming_window)
XinZhangMS 0:f7f1f0d76dd6 965 {
XinZhangMS 0:f7f1f0d76dd6 966 int result;
XinZhangMS 0:f7f1f0d76dd6 967
XinZhangMS 0:f7f1f0d76dd6 968 if ((session == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 969 (incoming_window == NULL))
XinZhangMS 0:f7f1f0d76dd6 970 {
XinZhangMS 0:f7f1f0d76dd6 971 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 972 }
XinZhangMS 0:f7f1f0d76dd6 973 else
XinZhangMS 0:f7f1f0d76dd6 974 {
XinZhangMS 0:f7f1f0d76dd6 975 SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)session;
XinZhangMS 0:f7f1f0d76dd6 976
XinZhangMS 0:f7f1f0d76dd6 977 *incoming_window = session_instance->incoming_window;
XinZhangMS 0:f7f1f0d76dd6 978
XinZhangMS 0:f7f1f0d76dd6 979 result = 0;
XinZhangMS 0:f7f1f0d76dd6 980 }
XinZhangMS 0:f7f1f0d76dd6 981
XinZhangMS 0:f7f1f0d76dd6 982 return result;
XinZhangMS 0:f7f1f0d76dd6 983 }
XinZhangMS 0:f7f1f0d76dd6 984
XinZhangMS 0:f7f1f0d76dd6 985 int session_set_outgoing_window(SESSION_HANDLE session, uint32_t outgoing_window)
XinZhangMS 0:f7f1f0d76dd6 986 {
XinZhangMS 0:f7f1f0d76dd6 987 int result;
XinZhangMS 0:f7f1f0d76dd6 988
XinZhangMS 0:f7f1f0d76dd6 989 if (session == NULL)
XinZhangMS 0:f7f1f0d76dd6 990 {
XinZhangMS 0:f7f1f0d76dd6 991 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 992 }
XinZhangMS 0:f7f1f0d76dd6 993 else
XinZhangMS 0:f7f1f0d76dd6 994 {
XinZhangMS 0:f7f1f0d76dd6 995 SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)session;
XinZhangMS 0:f7f1f0d76dd6 996
XinZhangMS 0:f7f1f0d76dd6 997 session_instance->outgoing_window = outgoing_window;
XinZhangMS 0:f7f1f0d76dd6 998
XinZhangMS 0:f7f1f0d76dd6 999 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1000 }
XinZhangMS 0:f7f1f0d76dd6 1001
XinZhangMS 0:f7f1f0d76dd6 1002 return result;
XinZhangMS 0:f7f1f0d76dd6 1003 }
XinZhangMS 0:f7f1f0d76dd6 1004
XinZhangMS 0:f7f1f0d76dd6 1005 int session_get_outgoing_window(SESSION_HANDLE session, uint32_t* outgoing_window)
XinZhangMS 0:f7f1f0d76dd6 1006 {
XinZhangMS 0:f7f1f0d76dd6 1007 int result;
XinZhangMS 0:f7f1f0d76dd6 1008
XinZhangMS 0:f7f1f0d76dd6 1009 if ((session == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 1010 (outgoing_window == NULL))
XinZhangMS 0:f7f1f0d76dd6 1011 {
XinZhangMS 0:f7f1f0d76dd6 1012 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1013 }
XinZhangMS 0:f7f1f0d76dd6 1014 else
XinZhangMS 0:f7f1f0d76dd6 1015 {
XinZhangMS 0:f7f1f0d76dd6 1016 SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)session;
XinZhangMS 0:f7f1f0d76dd6 1017
XinZhangMS 0:f7f1f0d76dd6 1018 *outgoing_window = session_instance->outgoing_window;
XinZhangMS 0:f7f1f0d76dd6 1019
XinZhangMS 0:f7f1f0d76dd6 1020 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1021 }
XinZhangMS 0:f7f1f0d76dd6 1022
XinZhangMS 0:f7f1f0d76dd6 1023 return result;
XinZhangMS 0:f7f1f0d76dd6 1024 }
XinZhangMS 0:f7f1f0d76dd6 1025
XinZhangMS 0:f7f1f0d76dd6 1026 int session_set_handle_max(SESSION_HANDLE session, handle handle_max)
XinZhangMS 0:f7f1f0d76dd6 1027 {
XinZhangMS 0:f7f1f0d76dd6 1028 int result;
XinZhangMS 0:f7f1f0d76dd6 1029
XinZhangMS 0:f7f1f0d76dd6 1030 if (session == NULL)
XinZhangMS 0:f7f1f0d76dd6 1031 {
XinZhangMS 0:f7f1f0d76dd6 1032 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1033 }
XinZhangMS 0:f7f1f0d76dd6 1034 else
XinZhangMS 0:f7f1f0d76dd6 1035 {
XinZhangMS 0:f7f1f0d76dd6 1036 SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)session;
XinZhangMS 0:f7f1f0d76dd6 1037
XinZhangMS 0:f7f1f0d76dd6 1038 session_instance->handle_max = handle_max;
XinZhangMS 0:f7f1f0d76dd6 1039
XinZhangMS 0:f7f1f0d76dd6 1040 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1041 }
XinZhangMS 0:f7f1f0d76dd6 1042
XinZhangMS 0:f7f1f0d76dd6 1043 return result;
XinZhangMS 0:f7f1f0d76dd6 1044 }
XinZhangMS 0:f7f1f0d76dd6 1045
XinZhangMS 0:f7f1f0d76dd6 1046 int session_get_handle_max(SESSION_HANDLE session, handle* handle_max)
XinZhangMS 0:f7f1f0d76dd6 1047 {
XinZhangMS 0:f7f1f0d76dd6 1048 int result;
XinZhangMS 0:f7f1f0d76dd6 1049
XinZhangMS 0:f7f1f0d76dd6 1050 if ((session == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 1051 (handle_max == NULL))
XinZhangMS 0:f7f1f0d76dd6 1052 {
XinZhangMS 0:f7f1f0d76dd6 1053 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1054 }
XinZhangMS 0:f7f1f0d76dd6 1055 else
XinZhangMS 0:f7f1f0d76dd6 1056 {
XinZhangMS 0:f7f1f0d76dd6 1057 SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)session;
XinZhangMS 0:f7f1f0d76dd6 1058
XinZhangMS 0:f7f1f0d76dd6 1059 *handle_max = session_instance->handle_max;
XinZhangMS 0:f7f1f0d76dd6 1060
XinZhangMS 0:f7f1f0d76dd6 1061 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1062 }
XinZhangMS 0:f7f1f0d76dd6 1063
XinZhangMS 0:f7f1f0d76dd6 1064 return result;
XinZhangMS 0:f7f1f0d76dd6 1065 }
XinZhangMS 0:f7f1f0d76dd6 1066
XinZhangMS 0:f7f1f0d76dd6 1067 LINK_ENDPOINT_HANDLE session_create_link_endpoint(SESSION_HANDLE session, const char* name)
XinZhangMS 0:f7f1f0d76dd6 1068 {
XinZhangMS 0:f7f1f0d76dd6 1069 LINK_ENDPOINT_INSTANCE* result;
XinZhangMS 0:f7f1f0d76dd6 1070
XinZhangMS 0:f7f1f0d76dd6 1071 /* Codes_S_R_S_SESSION_01_044: [If session, name or frame_received_callback is NULL, session_create_link_endpoint shall fail and return NULL.] */
XinZhangMS 0:f7f1f0d76dd6 1072 if ((session == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 1073 (name == NULL))
XinZhangMS 0:f7f1f0d76dd6 1074 {
XinZhangMS 0:f7f1f0d76dd6 1075 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 1076 }
XinZhangMS 0:f7f1f0d76dd6 1077 else
XinZhangMS 0:f7f1f0d76dd6 1078 {
XinZhangMS 0:f7f1f0d76dd6 1079 /* Codes_S_R_S_SESSION_01_043: [session_create_link_endpoint shall create a link endpoint associated with a given session and return a non-NULL handle to it.] */
XinZhangMS 0:f7f1f0d76dd6 1080 SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)session;
XinZhangMS 0:f7f1f0d76dd6 1081
XinZhangMS 0:f7f1f0d76dd6 1082 result = (LINK_ENDPOINT_INSTANCE*)malloc(sizeof(LINK_ENDPOINT_INSTANCE));
XinZhangMS 0:f7f1f0d76dd6 1083 /* Codes_S_R_S_SESSION_01_045: [If allocating memory for the link endpoint fails, session_create_link_endpoint shall fail and return NULL.] */
XinZhangMS 0:f7f1f0d76dd6 1084 if (result != NULL)
XinZhangMS 0:f7f1f0d76dd6 1085 {
XinZhangMS 0:f7f1f0d76dd6 1086 /* Codes_S_R_S_SESSION_01_046: [An unused handle shall be assigned to the link endpoint.] */
XinZhangMS 0:f7f1f0d76dd6 1087 handle selected_handle = 0;
XinZhangMS 0:f7f1f0d76dd6 1088 size_t i;
XinZhangMS 0:f7f1f0d76dd6 1089 size_t name_length;
XinZhangMS 0:f7f1f0d76dd6 1090
XinZhangMS 0:f7f1f0d76dd6 1091 for (i = 0; i < session_instance->link_endpoint_count; i++)
XinZhangMS 0:f7f1f0d76dd6 1092 {
XinZhangMS 0:f7f1f0d76dd6 1093 if (session_instance->link_endpoints[i]->output_handle > selected_handle)
XinZhangMS 0:f7f1f0d76dd6 1094 {
XinZhangMS 0:f7f1f0d76dd6 1095 break;
XinZhangMS 0:f7f1f0d76dd6 1096 }
XinZhangMS 0:f7f1f0d76dd6 1097
XinZhangMS 0:f7f1f0d76dd6 1098 selected_handle++;
XinZhangMS 0:f7f1f0d76dd6 1099 }
XinZhangMS 0:f7f1f0d76dd6 1100
XinZhangMS 0:f7f1f0d76dd6 1101 result->on_session_state_changed = NULL;
XinZhangMS 0:f7f1f0d76dd6 1102 result->on_session_flow_on = NULL;
XinZhangMS 0:f7f1f0d76dd6 1103 result->frame_received_callback = NULL;
XinZhangMS 0:f7f1f0d76dd6 1104 result->callback_context = NULL;
XinZhangMS 0:f7f1f0d76dd6 1105 result->output_handle = selected_handle;
XinZhangMS 0:f7f1f0d76dd6 1106 result->input_handle = 0xFFFFFFFF;
XinZhangMS 0:f7f1f0d76dd6 1107 result->link_endpoint_state = LINK_ENDPOINT_STATE_NOT_ATTACHED;
XinZhangMS 0:f7f1f0d76dd6 1108 name_length = strlen(name);
XinZhangMS 0:f7f1f0d76dd6 1109 result->name = (char*)malloc(name_length + 1);
XinZhangMS 0:f7f1f0d76dd6 1110 if (result->name == NULL)
XinZhangMS 0:f7f1f0d76dd6 1111 {
XinZhangMS 0:f7f1f0d76dd6 1112 /* Codes_S_R_S_SESSION_01_045: [If allocating memory for the link endpoint fails, session_create_link_endpoint shall fail and return NULL.] */
XinZhangMS 0:f7f1f0d76dd6 1113 free(result);
XinZhangMS 0:f7f1f0d76dd6 1114 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 1115 }
XinZhangMS 0:f7f1f0d76dd6 1116 else
XinZhangMS 0:f7f1f0d76dd6 1117 {
XinZhangMS 0:f7f1f0d76dd6 1118 LINK_ENDPOINT_INSTANCE** new_link_endpoints;
XinZhangMS 0:f7f1f0d76dd6 1119 (void)memcpy(result->name, name, name_length + 1);
XinZhangMS 0:f7f1f0d76dd6 1120 result->session = session;
XinZhangMS 0:f7f1f0d76dd6 1121
XinZhangMS 0:f7f1f0d76dd6 1122 new_link_endpoints = (LINK_ENDPOINT_INSTANCE**)realloc(session_instance->link_endpoints, sizeof(LINK_ENDPOINT_INSTANCE*) * (session_instance->link_endpoint_count + 1));
XinZhangMS 0:f7f1f0d76dd6 1123 if (new_link_endpoints == NULL)
XinZhangMS 0:f7f1f0d76dd6 1124 {
XinZhangMS 0:f7f1f0d76dd6 1125 /* Codes_S_R_S_SESSION_01_045: [If allocating memory for the link endpoint fails, session_create_link_endpoint shall fail and return NULL.] */
XinZhangMS 0:f7f1f0d76dd6 1126 free(result->name);
XinZhangMS 0:f7f1f0d76dd6 1127 free(result);
XinZhangMS 0:f7f1f0d76dd6 1128 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 1129 }
XinZhangMS 0:f7f1f0d76dd6 1130 else
XinZhangMS 0:f7f1f0d76dd6 1131 {
XinZhangMS 0:f7f1f0d76dd6 1132 session_instance->link_endpoints = new_link_endpoints;
XinZhangMS 0:f7f1f0d76dd6 1133
XinZhangMS 0:f7f1f0d76dd6 1134 if (session_instance->link_endpoint_count - selected_handle > 0)
XinZhangMS 0:f7f1f0d76dd6 1135 {
XinZhangMS 0:f7f1f0d76dd6 1136 (void)memmove(&session_instance->link_endpoints[selected_handle + 1], &session_instance->link_endpoints[selected_handle], (session_instance->link_endpoint_count - selected_handle) * sizeof(LINK_ENDPOINT_INSTANCE*));
XinZhangMS 0:f7f1f0d76dd6 1137 }
XinZhangMS 0:f7f1f0d76dd6 1138
XinZhangMS 0:f7f1f0d76dd6 1139 session_instance->link_endpoints[selected_handle] = result;
XinZhangMS 0:f7f1f0d76dd6 1140 session_instance->link_endpoint_count++;
XinZhangMS 0:f7f1f0d76dd6 1141 }
XinZhangMS 0:f7f1f0d76dd6 1142 }
XinZhangMS 0:f7f1f0d76dd6 1143 }
XinZhangMS 0:f7f1f0d76dd6 1144 }
XinZhangMS 0:f7f1f0d76dd6 1145
XinZhangMS 0:f7f1f0d76dd6 1146 return result;
XinZhangMS 0:f7f1f0d76dd6 1147 }
XinZhangMS 0:f7f1f0d76dd6 1148
XinZhangMS 0:f7f1f0d76dd6 1149 void session_destroy_link_endpoint(LINK_ENDPOINT_HANDLE link_endpoint)
XinZhangMS 0:f7f1f0d76dd6 1150 {
XinZhangMS 0:f7f1f0d76dd6 1151 if (link_endpoint != NULL)
XinZhangMS 0:f7f1f0d76dd6 1152 {
XinZhangMS 0:f7f1f0d76dd6 1153 LINK_ENDPOINT_INSTANCE* endpoint_instance = (LINK_ENDPOINT_INSTANCE*)link_endpoint;
XinZhangMS 0:f7f1f0d76dd6 1154
XinZhangMS 0:f7f1f0d76dd6 1155 if (endpoint_instance->link_endpoint_state == LINK_ENDPOINT_STATE_ATTACHED)
XinZhangMS 0:f7f1f0d76dd6 1156 {
XinZhangMS 0:f7f1f0d76dd6 1157 endpoint_instance->link_endpoint_state = LINK_ENDPOINT_STATE_DETACHING;
XinZhangMS 0:f7f1f0d76dd6 1158 }
XinZhangMS 0:f7f1f0d76dd6 1159 else
XinZhangMS 0:f7f1f0d76dd6 1160 {
XinZhangMS 0:f7f1f0d76dd6 1161 remove_link_endpoint(link_endpoint);
XinZhangMS 0:f7f1f0d76dd6 1162 free_link_endpoint(link_endpoint);
XinZhangMS 0:f7f1f0d76dd6 1163 }
XinZhangMS 0:f7f1f0d76dd6 1164 }
XinZhangMS 0:f7f1f0d76dd6 1165 }
XinZhangMS 0:f7f1f0d76dd6 1166
XinZhangMS 0:f7f1f0d76dd6 1167 int session_start_link_endpoint(LINK_ENDPOINT_HANDLE link_endpoint, ON_ENDPOINT_FRAME_RECEIVED frame_received_callback, ON_SESSION_STATE_CHANGED on_session_state_changed, ON_SESSION_FLOW_ON on_session_flow_on, void* context)
XinZhangMS 0:f7f1f0d76dd6 1168 {
XinZhangMS 0:f7f1f0d76dd6 1169 int result;
XinZhangMS 0:f7f1f0d76dd6 1170
XinZhangMS 0:f7f1f0d76dd6 1171 if ((link_endpoint == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 1172 (frame_received_callback == NULL))
XinZhangMS 0:f7f1f0d76dd6 1173 {
XinZhangMS 0:f7f1f0d76dd6 1174 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1175 }
XinZhangMS 0:f7f1f0d76dd6 1176 else
XinZhangMS 0:f7f1f0d76dd6 1177 {
XinZhangMS 0:f7f1f0d76dd6 1178 link_endpoint->frame_received_callback = frame_received_callback;
XinZhangMS 0:f7f1f0d76dd6 1179 link_endpoint->on_session_state_changed = on_session_state_changed;
XinZhangMS 0:f7f1f0d76dd6 1180 link_endpoint->on_session_flow_on = on_session_flow_on;
XinZhangMS 0:f7f1f0d76dd6 1181 link_endpoint->callback_context = context;
XinZhangMS 0:f7f1f0d76dd6 1182 link_endpoint->link_endpoint_state = LINK_ENDPOINT_STATE_NOT_ATTACHED;
XinZhangMS 0:f7f1f0d76dd6 1183
XinZhangMS 0:f7f1f0d76dd6 1184 if (link_endpoint->on_session_state_changed != NULL)
XinZhangMS 0:f7f1f0d76dd6 1185 {
XinZhangMS 0:f7f1f0d76dd6 1186 link_endpoint->on_session_state_changed(link_endpoint->callback_context, link_endpoint->session->session_state, link_endpoint->session->previous_session_state);
XinZhangMS 0:f7f1f0d76dd6 1187 }
XinZhangMS 0:f7f1f0d76dd6 1188
XinZhangMS 0:f7f1f0d76dd6 1189 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1190 }
XinZhangMS 0:f7f1f0d76dd6 1191
XinZhangMS 0:f7f1f0d76dd6 1192 return result;
XinZhangMS 0:f7f1f0d76dd6 1193 }
XinZhangMS 0:f7f1f0d76dd6 1194
XinZhangMS 0:f7f1f0d76dd6 1195 static int encode_frame(LINK_ENDPOINT_HANDLE link_endpoint, AMQP_VALUE performative, PAYLOAD* payloads, size_t payload_count)
XinZhangMS 0:f7f1f0d76dd6 1196 {
XinZhangMS 0:f7f1f0d76dd6 1197 int result;
XinZhangMS 0:f7f1f0d76dd6 1198
XinZhangMS 0:f7f1f0d76dd6 1199 if ((link_endpoint == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 1200 (performative == NULL))
XinZhangMS 0:f7f1f0d76dd6 1201 {
XinZhangMS 0:f7f1f0d76dd6 1202 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1203 }
XinZhangMS 0:f7f1f0d76dd6 1204 else
XinZhangMS 0:f7f1f0d76dd6 1205 {
XinZhangMS 0:f7f1f0d76dd6 1206 LINK_ENDPOINT_INSTANCE* link_endpoint_instance = (LINK_ENDPOINT_INSTANCE*)link_endpoint;
XinZhangMS 0:f7f1f0d76dd6 1207 SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)link_endpoint_instance->session;
XinZhangMS 0:f7f1f0d76dd6 1208
XinZhangMS 0:f7f1f0d76dd6 1209 if (connection_encode_frame(session_instance->endpoint, performative, payloads, payload_count, NULL, NULL) != 0)
XinZhangMS 0:f7f1f0d76dd6 1210 {
XinZhangMS 0:f7f1f0d76dd6 1211 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1212 }
XinZhangMS 0:f7f1f0d76dd6 1213 else
XinZhangMS 0:f7f1f0d76dd6 1214 {
XinZhangMS 0:f7f1f0d76dd6 1215 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1216 }
XinZhangMS 0:f7f1f0d76dd6 1217 }
XinZhangMS 0:f7f1f0d76dd6 1218
XinZhangMS 0:f7f1f0d76dd6 1219 return result;
XinZhangMS 0:f7f1f0d76dd6 1220 }
XinZhangMS 0:f7f1f0d76dd6 1221
XinZhangMS 0:f7f1f0d76dd6 1222 int session_send_flow(LINK_ENDPOINT_HANDLE link_endpoint, FLOW_HANDLE flow)
XinZhangMS 0:f7f1f0d76dd6 1223 {
XinZhangMS 0:f7f1f0d76dd6 1224 int result;
XinZhangMS 0:f7f1f0d76dd6 1225
XinZhangMS 0:f7f1f0d76dd6 1226 if ((link_endpoint == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 1227 (flow == NULL))
XinZhangMS 0:f7f1f0d76dd6 1228 {
XinZhangMS 0:f7f1f0d76dd6 1229 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1230 }
XinZhangMS 0:f7f1f0d76dd6 1231 else
XinZhangMS 0:f7f1f0d76dd6 1232 {
XinZhangMS 0:f7f1f0d76dd6 1233 LINK_ENDPOINT_INSTANCE* link_endpoint_instance = (LINK_ENDPOINT_INSTANCE*)link_endpoint;
XinZhangMS 0:f7f1f0d76dd6 1234 SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)link_endpoint_instance->session;
XinZhangMS 0:f7f1f0d76dd6 1235
XinZhangMS 0:f7f1f0d76dd6 1236 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1237
XinZhangMS 0:f7f1f0d76dd6 1238 if (session_instance->session_state == SESSION_STATE_BEGIN_RCVD)
XinZhangMS 0:f7f1f0d76dd6 1239 {
XinZhangMS 0:f7f1f0d76dd6 1240 if (flow_set_next_incoming_id(flow, session_instance->next_incoming_id) != 0)
XinZhangMS 0:f7f1f0d76dd6 1241 {
XinZhangMS 0:f7f1f0d76dd6 1242 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1243 }
XinZhangMS 0:f7f1f0d76dd6 1244 }
XinZhangMS 0:f7f1f0d76dd6 1245
XinZhangMS 0:f7f1f0d76dd6 1246 if (result == 0)
XinZhangMS 0:f7f1f0d76dd6 1247 {
XinZhangMS 0:f7f1f0d76dd6 1248 if ((flow_set_next_incoming_id(flow, session_instance->next_incoming_id) != 0) ||
XinZhangMS 0:f7f1f0d76dd6 1249 (flow_set_incoming_window(flow, session_instance->incoming_window) != 0) ||
XinZhangMS 0:f7f1f0d76dd6 1250 (flow_set_next_outgoing_id(flow, session_instance->next_outgoing_id) != 0) ||
XinZhangMS 0:f7f1f0d76dd6 1251 (flow_set_outgoing_window(flow, session_instance->outgoing_window) != 0) ||
XinZhangMS 0:f7f1f0d76dd6 1252 (flow_set_handle(flow, link_endpoint_instance->output_handle) != 0))
XinZhangMS 0:f7f1f0d76dd6 1253 {
XinZhangMS 0:f7f1f0d76dd6 1254 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1255 }
XinZhangMS 0:f7f1f0d76dd6 1256 else
XinZhangMS 0:f7f1f0d76dd6 1257 {
XinZhangMS 0:f7f1f0d76dd6 1258 AMQP_VALUE flow_performative_value = amqpvalue_create_flow(flow);
XinZhangMS 0:f7f1f0d76dd6 1259 if (flow_performative_value == NULL)
XinZhangMS 0:f7f1f0d76dd6 1260 {
XinZhangMS 0:f7f1f0d76dd6 1261 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1262 }
XinZhangMS 0:f7f1f0d76dd6 1263 else
XinZhangMS 0:f7f1f0d76dd6 1264 {
XinZhangMS 0:f7f1f0d76dd6 1265 if (encode_frame(link_endpoint, flow_performative_value, NULL, 0) != 0)
XinZhangMS 0:f7f1f0d76dd6 1266 {
XinZhangMS 0:f7f1f0d76dd6 1267 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1268 }
XinZhangMS 0:f7f1f0d76dd6 1269 else
XinZhangMS 0:f7f1f0d76dd6 1270 {
XinZhangMS 0:f7f1f0d76dd6 1271 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1272 }
XinZhangMS 0:f7f1f0d76dd6 1273
XinZhangMS 0:f7f1f0d76dd6 1274 amqpvalue_destroy(flow_performative_value);
XinZhangMS 0:f7f1f0d76dd6 1275 }
XinZhangMS 0:f7f1f0d76dd6 1276 }
XinZhangMS 0:f7f1f0d76dd6 1277 }
XinZhangMS 0:f7f1f0d76dd6 1278 }
XinZhangMS 0:f7f1f0d76dd6 1279
XinZhangMS 0:f7f1f0d76dd6 1280 return result;
XinZhangMS 0:f7f1f0d76dd6 1281 }
XinZhangMS 0:f7f1f0d76dd6 1282
XinZhangMS 0:f7f1f0d76dd6 1283 int session_send_attach(LINK_ENDPOINT_HANDLE link_endpoint, ATTACH_HANDLE attach)
XinZhangMS 0:f7f1f0d76dd6 1284 {
XinZhangMS 0:f7f1f0d76dd6 1285 int result;
XinZhangMS 0:f7f1f0d76dd6 1286
XinZhangMS 0:f7f1f0d76dd6 1287 if ((link_endpoint == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 1288 (attach == NULL))
XinZhangMS 0:f7f1f0d76dd6 1289 {
XinZhangMS 0:f7f1f0d76dd6 1290 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1291 }
XinZhangMS 0:f7f1f0d76dd6 1292 else
XinZhangMS 0:f7f1f0d76dd6 1293 {
XinZhangMS 0:f7f1f0d76dd6 1294 LINK_ENDPOINT_INSTANCE* link_endpoint_instance = (LINK_ENDPOINT_INSTANCE*)link_endpoint;
XinZhangMS 0:f7f1f0d76dd6 1295
XinZhangMS 0:f7f1f0d76dd6 1296 if (attach_set_handle(attach, link_endpoint_instance->output_handle) != 0)
XinZhangMS 0:f7f1f0d76dd6 1297 {
XinZhangMS 0:f7f1f0d76dd6 1298 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1299 }
XinZhangMS 0:f7f1f0d76dd6 1300 else
XinZhangMS 0:f7f1f0d76dd6 1301 {
XinZhangMS 0:f7f1f0d76dd6 1302 AMQP_VALUE attach_performative_value = amqpvalue_create_attach(attach);
XinZhangMS 0:f7f1f0d76dd6 1303 if (attach_performative_value == NULL)
XinZhangMS 0:f7f1f0d76dd6 1304 {
XinZhangMS 0:f7f1f0d76dd6 1305 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1306 }
XinZhangMS 0:f7f1f0d76dd6 1307 else
XinZhangMS 0:f7f1f0d76dd6 1308 {
XinZhangMS 0:f7f1f0d76dd6 1309 if (encode_frame(link_endpoint, attach_performative_value, NULL, 0) != 0)
XinZhangMS 0:f7f1f0d76dd6 1310 {
XinZhangMS 0:f7f1f0d76dd6 1311 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1312 }
XinZhangMS 0:f7f1f0d76dd6 1313 else
XinZhangMS 0:f7f1f0d76dd6 1314 {
XinZhangMS 0:f7f1f0d76dd6 1315 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1316 }
XinZhangMS 0:f7f1f0d76dd6 1317
XinZhangMS 0:f7f1f0d76dd6 1318 amqpvalue_destroy(attach_performative_value);
XinZhangMS 0:f7f1f0d76dd6 1319 }
XinZhangMS 0:f7f1f0d76dd6 1320 }
XinZhangMS 0:f7f1f0d76dd6 1321 }
XinZhangMS 0:f7f1f0d76dd6 1322
XinZhangMS 0:f7f1f0d76dd6 1323 return result;
XinZhangMS 0:f7f1f0d76dd6 1324 }
XinZhangMS 0:f7f1f0d76dd6 1325
XinZhangMS 0:f7f1f0d76dd6 1326 int session_send_disposition(LINK_ENDPOINT_HANDLE link_endpoint, DISPOSITION_HANDLE disposition)
XinZhangMS 0:f7f1f0d76dd6 1327 {
XinZhangMS 0:f7f1f0d76dd6 1328 int result;
XinZhangMS 0:f7f1f0d76dd6 1329
XinZhangMS 0:f7f1f0d76dd6 1330 if ((link_endpoint == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 1331 (disposition == NULL))
XinZhangMS 0:f7f1f0d76dd6 1332 {
XinZhangMS 0:f7f1f0d76dd6 1333 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1334 }
XinZhangMS 0:f7f1f0d76dd6 1335 else
XinZhangMS 0:f7f1f0d76dd6 1336 {
XinZhangMS 0:f7f1f0d76dd6 1337 AMQP_VALUE disposition_performative_value = amqpvalue_create_disposition(disposition);
XinZhangMS 0:f7f1f0d76dd6 1338 if (disposition_performative_value == NULL)
XinZhangMS 0:f7f1f0d76dd6 1339 {
XinZhangMS 0:f7f1f0d76dd6 1340 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1341 }
XinZhangMS 0:f7f1f0d76dd6 1342 else
XinZhangMS 0:f7f1f0d76dd6 1343 {
XinZhangMS 0:f7f1f0d76dd6 1344 if (encode_frame(link_endpoint, disposition_performative_value, NULL, 0) != 0)
XinZhangMS 0:f7f1f0d76dd6 1345 {
XinZhangMS 0:f7f1f0d76dd6 1346 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1347 }
XinZhangMS 0:f7f1f0d76dd6 1348 else
XinZhangMS 0:f7f1f0d76dd6 1349 {
XinZhangMS 0:f7f1f0d76dd6 1350 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1351 }
XinZhangMS 0:f7f1f0d76dd6 1352
XinZhangMS 0:f7f1f0d76dd6 1353 amqpvalue_destroy(disposition_performative_value);
XinZhangMS 0:f7f1f0d76dd6 1354 }
XinZhangMS 0:f7f1f0d76dd6 1355 }
XinZhangMS 0:f7f1f0d76dd6 1356
XinZhangMS 0:f7f1f0d76dd6 1357 return result;
XinZhangMS 0:f7f1f0d76dd6 1358 }
XinZhangMS 0:f7f1f0d76dd6 1359
XinZhangMS 0:f7f1f0d76dd6 1360 int session_send_detach(LINK_ENDPOINT_HANDLE link_endpoint, DETACH_HANDLE detach)
XinZhangMS 0:f7f1f0d76dd6 1361 {
XinZhangMS 0:f7f1f0d76dd6 1362 int result;
XinZhangMS 0:f7f1f0d76dd6 1363
XinZhangMS 0:f7f1f0d76dd6 1364 if ((link_endpoint == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 1365 (detach == NULL))
XinZhangMS 0:f7f1f0d76dd6 1366 {
XinZhangMS 0:f7f1f0d76dd6 1367 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1368 }
XinZhangMS 0:f7f1f0d76dd6 1369 else
XinZhangMS 0:f7f1f0d76dd6 1370 {
XinZhangMS 0:f7f1f0d76dd6 1371 LINK_ENDPOINT_INSTANCE* link_endpoint_instance = (LINK_ENDPOINT_INSTANCE*)link_endpoint;
XinZhangMS 0:f7f1f0d76dd6 1372
XinZhangMS 0:f7f1f0d76dd6 1373 if (detach_set_handle(detach, link_endpoint_instance->output_handle) != 0)
XinZhangMS 0:f7f1f0d76dd6 1374 {
XinZhangMS 0:f7f1f0d76dd6 1375 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1376 }
XinZhangMS 0:f7f1f0d76dd6 1377 else
XinZhangMS 0:f7f1f0d76dd6 1378 {
XinZhangMS 0:f7f1f0d76dd6 1379 AMQP_VALUE detach_performative_value = amqpvalue_create_detach(detach);
XinZhangMS 0:f7f1f0d76dd6 1380 if (detach_performative_value == NULL)
XinZhangMS 0:f7f1f0d76dd6 1381 {
XinZhangMS 0:f7f1f0d76dd6 1382 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1383 }
XinZhangMS 0:f7f1f0d76dd6 1384 else
XinZhangMS 0:f7f1f0d76dd6 1385 {
XinZhangMS 0:f7f1f0d76dd6 1386 if (encode_frame(link_endpoint, detach_performative_value, NULL, 0) != 0)
XinZhangMS 0:f7f1f0d76dd6 1387 {
XinZhangMS 0:f7f1f0d76dd6 1388 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1389 }
XinZhangMS 0:f7f1f0d76dd6 1390 else
XinZhangMS 0:f7f1f0d76dd6 1391 {
XinZhangMS 0:f7f1f0d76dd6 1392 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1393 }
XinZhangMS 0:f7f1f0d76dd6 1394
XinZhangMS 0:f7f1f0d76dd6 1395 amqpvalue_destroy(detach_performative_value);
XinZhangMS 0:f7f1f0d76dd6 1396 }
XinZhangMS 0:f7f1f0d76dd6 1397 }
XinZhangMS 0:f7f1f0d76dd6 1398 }
XinZhangMS 0:f7f1f0d76dd6 1399
XinZhangMS 0:f7f1f0d76dd6 1400 return result;
XinZhangMS 0:f7f1f0d76dd6 1401 }
XinZhangMS 0:f7f1f0d76dd6 1402
XinZhangMS 0:f7f1f0d76dd6 1403 /* Codes_S_R_S_SESSION_01_051: [session_send_transfer shall send a transfer frame with the performative indicated in the transfer argument.] */
XinZhangMS 0:f7f1f0d76dd6 1404 SESSION_SEND_TRANSFER_RESULT session_send_transfer(LINK_ENDPOINT_HANDLE link_endpoint, TRANSFER_HANDLE transfer, PAYLOAD* payloads, size_t payload_count, delivery_number* delivery_id, ON_SEND_COMPLETE on_send_complete, void* callback_context)
XinZhangMS 0:f7f1f0d76dd6 1405 {
XinZhangMS 0:f7f1f0d76dd6 1406 SESSION_SEND_TRANSFER_RESULT result;
XinZhangMS 0:f7f1f0d76dd6 1407
XinZhangMS 0:f7f1f0d76dd6 1408 /* Codes_S_R_S_SESSION_01_054: [If link_endpoint or transfer is NULL, session_send_transfer shall fail and return a non-zero value.] */
XinZhangMS 0:f7f1f0d76dd6 1409 if ((link_endpoint == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 1410 (transfer == NULL))
XinZhangMS 0:f7f1f0d76dd6 1411 {
XinZhangMS 0:f7f1f0d76dd6 1412 result = SESSION_SEND_TRANSFER_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1413 }
XinZhangMS 0:f7f1f0d76dd6 1414 else
XinZhangMS 0:f7f1f0d76dd6 1415 {
XinZhangMS 0:f7f1f0d76dd6 1416 LINK_ENDPOINT_INSTANCE* link_endpoint_instance = (LINK_ENDPOINT_INSTANCE*)link_endpoint;
XinZhangMS 0:f7f1f0d76dd6 1417 SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)link_endpoint_instance->session;
XinZhangMS 0:f7f1f0d76dd6 1418
XinZhangMS 0:f7f1f0d76dd6 1419 /* Codes_S_R_S_SESSION_01_059: [When session_send_transfer is called while the session is not in the MAPPED state, session_send_transfer shall fail and return a non-zero value.] */
XinZhangMS 0:f7f1f0d76dd6 1420 if (session_instance->session_state != SESSION_STATE_MAPPED)
XinZhangMS 0:f7f1f0d76dd6 1421 {
XinZhangMS 0:f7f1f0d76dd6 1422 result = SESSION_SEND_TRANSFER_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1423 }
XinZhangMS 0:f7f1f0d76dd6 1424 else
XinZhangMS 0:f7f1f0d76dd6 1425 {
XinZhangMS 0:f7f1f0d76dd6 1426 size_t payload_size = 0;
XinZhangMS 0:f7f1f0d76dd6 1427 size_t i;
XinZhangMS 0:f7f1f0d76dd6 1428
XinZhangMS 0:f7f1f0d76dd6 1429 for (i = 0; i < payload_count; i++)
XinZhangMS 0:f7f1f0d76dd6 1430 {
XinZhangMS 0:f7f1f0d76dd6 1431 if ((payloads[i].length > UINT32_MAX) ||
XinZhangMS 0:f7f1f0d76dd6 1432 (payload_size + payloads[i].length < payload_size))
XinZhangMS 0:f7f1f0d76dd6 1433 {
XinZhangMS 0:f7f1f0d76dd6 1434 break;
XinZhangMS 0:f7f1f0d76dd6 1435 }
XinZhangMS 0:f7f1f0d76dd6 1436
XinZhangMS 0:f7f1f0d76dd6 1437 payload_size += payloads[i].length;
XinZhangMS 0:f7f1f0d76dd6 1438 }
XinZhangMS 0:f7f1f0d76dd6 1439
XinZhangMS 0:f7f1f0d76dd6 1440 if ((i < payload_count) ||
XinZhangMS 0:f7f1f0d76dd6 1441 (payload_size > UINT32_MAX))
XinZhangMS 0:f7f1f0d76dd6 1442 {
XinZhangMS 0:f7f1f0d76dd6 1443 result = SESSION_SEND_TRANSFER_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1444 }
XinZhangMS 0:f7f1f0d76dd6 1445 else
XinZhangMS 0:f7f1f0d76dd6 1446 {
XinZhangMS 0:f7f1f0d76dd6 1447 if (session_instance->remote_incoming_window == 0)
XinZhangMS 0:f7f1f0d76dd6 1448 {
XinZhangMS 0:f7f1f0d76dd6 1449 result = SESSION_SEND_TRANSFER_BUSY;
XinZhangMS 0:f7f1f0d76dd6 1450 }
XinZhangMS 0:f7f1f0d76dd6 1451 else
XinZhangMS 0:f7f1f0d76dd6 1452 {
XinZhangMS 0:f7f1f0d76dd6 1453 /* Codes_S_R_S_SESSION_01_012: [The session endpoint assigns each outgoing transfer frame an implicit transfer-id from a session scoped sequence.] */
XinZhangMS 0:f7f1f0d76dd6 1454 /* Codes_S_R_S_SESSION_01_027: [sending a transfer Upon sending a transfer, the sending endpoint will increment its next-outgoing-id] */
XinZhangMS 0:f7f1f0d76dd6 1455 *delivery_id = session_instance->next_outgoing_id;
XinZhangMS 0:f7f1f0d76dd6 1456 if ((transfer_set_handle(transfer, link_endpoint_instance->output_handle) != 0) ||
XinZhangMS 0:f7f1f0d76dd6 1457 (transfer_set_delivery_id(transfer, *delivery_id) != 0) ||
XinZhangMS 0:f7f1f0d76dd6 1458 (transfer_set_more(transfer, false) != 0))
XinZhangMS 0:f7f1f0d76dd6 1459 {
XinZhangMS 0:f7f1f0d76dd6 1460 /* Codes_S_R_S_SESSION_01_058: [When any other error occurs, session_send_transfer shall fail and return a non-zero value.] */
XinZhangMS 0:f7f1f0d76dd6 1461 result = SESSION_SEND_TRANSFER_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1462 }
XinZhangMS 0:f7f1f0d76dd6 1463 else
XinZhangMS 0:f7f1f0d76dd6 1464 {
XinZhangMS 0:f7f1f0d76dd6 1465 AMQP_VALUE transfer_value;
XinZhangMS 0:f7f1f0d76dd6 1466
XinZhangMS 0:f7f1f0d76dd6 1467 transfer_value = amqpvalue_create_transfer(transfer);
XinZhangMS 0:f7f1f0d76dd6 1468 if (transfer_value == NULL)
XinZhangMS 0:f7f1f0d76dd6 1469 {
XinZhangMS 0:f7f1f0d76dd6 1470 /* Codes_S_R_S_SESSION_01_058: [When any other error occurs, session_send_transfer shall fail and return a non-zero value.] */
XinZhangMS 0:f7f1f0d76dd6 1471 result = SESSION_SEND_TRANSFER_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1472 }
XinZhangMS 0:f7f1f0d76dd6 1473 else
XinZhangMS 0:f7f1f0d76dd6 1474 {
XinZhangMS 0:f7f1f0d76dd6 1475 uint32_t available_frame_size;
XinZhangMS 0:f7f1f0d76dd6 1476 size_t encoded_size;
XinZhangMS 0:f7f1f0d76dd6 1477
XinZhangMS 0:f7f1f0d76dd6 1478 if ((connection_get_remote_max_frame_size(session_instance->connection, &available_frame_size) != 0) ||
XinZhangMS 0:f7f1f0d76dd6 1479 (amqpvalue_get_encoded_size(transfer_value, &encoded_size) != 0))
XinZhangMS 0:f7f1f0d76dd6 1480 {
XinZhangMS 0:f7f1f0d76dd6 1481 result = SESSION_SEND_TRANSFER_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1482 }
XinZhangMS 0:f7f1f0d76dd6 1483 else
XinZhangMS 0:f7f1f0d76dd6 1484 {
XinZhangMS 0:f7f1f0d76dd6 1485 payload_size = 0;
XinZhangMS 0:f7f1f0d76dd6 1486
XinZhangMS 0:f7f1f0d76dd6 1487 for (i = 0; i < payload_count; i++)
XinZhangMS 0:f7f1f0d76dd6 1488 {
XinZhangMS 0:f7f1f0d76dd6 1489 payload_size += payloads[i].length;
XinZhangMS 0:f7f1f0d76dd6 1490 }
XinZhangMS 0:f7f1f0d76dd6 1491
XinZhangMS 0:f7f1f0d76dd6 1492 available_frame_size -= (uint32_t)encoded_size;
XinZhangMS 0:f7f1f0d76dd6 1493 available_frame_size -= 8;
XinZhangMS 0:f7f1f0d76dd6 1494
XinZhangMS 0:f7f1f0d76dd6 1495 if (available_frame_size >= payload_size)
XinZhangMS 0:f7f1f0d76dd6 1496 {
XinZhangMS 0:f7f1f0d76dd6 1497 /* Codes_S_R_S_SESSION_01_055: [The encoding of the frame shall be done by calling connection_encode_frame and passing as arguments: the connection handle associated with the session, the transfer performative and the payload chunks passed to session_send_transfer.] */
XinZhangMS 0:f7f1f0d76dd6 1498 if (connection_encode_frame(session_instance->endpoint, transfer_value, payloads, payload_count, on_send_complete, callback_context) != 0)
XinZhangMS 0:f7f1f0d76dd6 1499 {
XinZhangMS 0:f7f1f0d76dd6 1500 /* Codes_S_R_S_SESSION_01_056: [If connection_encode_frame fails then session_send_transfer shall fail and return a non-zero value.] */
XinZhangMS 0:f7f1f0d76dd6 1501 result = SESSION_SEND_TRANSFER_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1502 }
XinZhangMS 0:f7f1f0d76dd6 1503 else
XinZhangMS 0:f7f1f0d76dd6 1504 {
XinZhangMS 0:f7f1f0d76dd6 1505 /* Codes_S_R_S_SESSION_01_018: [is incremented after each successive transfer according to RFC-1982 [RFC1982] serial number arithmetic.] */
XinZhangMS 0:f7f1f0d76dd6 1506 session_instance->next_outgoing_id++;
XinZhangMS 0:f7f1f0d76dd6 1507 session_instance->remote_incoming_window--;
XinZhangMS 0:f7f1f0d76dd6 1508 session_instance->outgoing_window--;
XinZhangMS 0:f7f1f0d76dd6 1509
XinZhangMS 0:f7f1f0d76dd6 1510 /* Codes_S_R_S_SESSION_01_053: [On success, session_send_transfer shall return 0.] */
XinZhangMS 0:f7f1f0d76dd6 1511 result = SESSION_SEND_TRANSFER_OK;
XinZhangMS 0:f7f1f0d76dd6 1512 }
XinZhangMS 0:f7f1f0d76dd6 1513 }
XinZhangMS 0:f7f1f0d76dd6 1514 else
XinZhangMS 0:f7f1f0d76dd6 1515 {
XinZhangMS 0:f7f1f0d76dd6 1516 size_t current_payload_index = 0;
XinZhangMS 0:f7f1f0d76dd6 1517 uint32_t current_payload_pos = 0;
XinZhangMS 0:f7f1f0d76dd6 1518
XinZhangMS 0:f7f1f0d76dd6 1519 /* break it down into different deliveries */
XinZhangMS 0:f7f1f0d76dd6 1520 while (payload_size > 0)
XinZhangMS 0:f7f1f0d76dd6 1521 {
XinZhangMS 0:f7f1f0d76dd6 1522 uint32_t transfer_frame_payload_count = 0;
XinZhangMS 0:f7f1f0d76dd6 1523 uint32_t current_transfer_frame_payload_size = (uint32_t)payload_size;
XinZhangMS 0:f7f1f0d76dd6 1524 uint32_t byte_counter;
XinZhangMS 0:f7f1f0d76dd6 1525 size_t temp_current_payload_index = current_payload_index;
XinZhangMS 0:f7f1f0d76dd6 1526 uint32_t temp_current_payload_pos = current_payload_pos;
XinZhangMS 0:f7f1f0d76dd6 1527 AMQP_VALUE multi_transfer_amqp_value;
XinZhangMS 0:f7f1f0d76dd6 1528 PAYLOAD* transfer_frame_payloads;
XinZhangMS 0:f7f1f0d76dd6 1529 bool more;
XinZhangMS 0:f7f1f0d76dd6 1530
XinZhangMS 0:f7f1f0d76dd6 1531 if (current_transfer_frame_payload_size > available_frame_size)
XinZhangMS 0:f7f1f0d76dd6 1532 {
XinZhangMS 0:f7f1f0d76dd6 1533 current_transfer_frame_payload_size = available_frame_size;
XinZhangMS 0:f7f1f0d76dd6 1534 }
XinZhangMS 0:f7f1f0d76dd6 1535
XinZhangMS 0:f7f1f0d76dd6 1536 if (available_frame_size >= payload_size)
XinZhangMS 0:f7f1f0d76dd6 1537 {
XinZhangMS 0:f7f1f0d76dd6 1538 more = false;
XinZhangMS 0:f7f1f0d76dd6 1539 }
XinZhangMS 0:f7f1f0d76dd6 1540 else
XinZhangMS 0:f7f1f0d76dd6 1541 {
XinZhangMS 0:f7f1f0d76dd6 1542 more = true;
XinZhangMS 0:f7f1f0d76dd6 1543 }
XinZhangMS 0:f7f1f0d76dd6 1544
XinZhangMS 0:f7f1f0d76dd6 1545 if (transfer_set_more(transfer, more) != 0)
XinZhangMS 0:f7f1f0d76dd6 1546 {
XinZhangMS 0:f7f1f0d76dd6 1547 break;
XinZhangMS 0:f7f1f0d76dd6 1548 }
XinZhangMS 0:f7f1f0d76dd6 1549
XinZhangMS 0:f7f1f0d76dd6 1550 multi_transfer_amqp_value = amqpvalue_create_transfer(transfer);
XinZhangMS 0:f7f1f0d76dd6 1551 if (multi_transfer_amqp_value == NULL)
XinZhangMS 0:f7f1f0d76dd6 1552 {
XinZhangMS 0:f7f1f0d76dd6 1553 break;
XinZhangMS 0:f7f1f0d76dd6 1554 }
XinZhangMS 0:f7f1f0d76dd6 1555
XinZhangMS 0:f7f1f0d76dd6 1556 byte_counter = current_transfer_frame_payload_size;
XinZhangMS 0:f7f1f0d76dd6 1557 while (byte_counter > 0)
XinZhangMS 0:f7f1f0d76dd6 1558 {
XinZhangMS 0:f7f1f0d76dd6 1559 if (payloads[temp_current_payload_index].length - temp_current_payload_pos >= byte_counter)
XinZhangMS 0:f7f1f0d76dd6 1560 {
XinZhangMS 0:f7f1f0d76dd6 1561 /* more data than we need */
XinZhangMS 0:f7f1f0d76dd6 1562 temp_current_payload_pos += byte_counter;
XinZhangMS 0:f7f1f0d76dd6 1563 byte_counter = 0;
XinZhangMS 0:f7f1f0d76dd6 1564 }
XinZhangMS 0:f7f1f0d76dd6 1565 else
XinZhangMS 0:f7f1f0d76dd6 1566 {
XinZhangMS 0:f7f1f0d76dd6 1567 byte_counter -= (uint32_t)payloads[temp_current_payload_index].length - temp_current_payload_pos;
XinZhangMS 0:f7f1f0d76dd6 1568 temp_current_payload_index++;
XinZhangMS 0:f7f1f0d76dd6 1569 temp_current_payload_pos = 0;
XinZhangMS 0:f7f1f0d76dd6 1570 }
XinZhangMS 0:f7f1f0d76dd6 1571 }
XinZhangMS 0:f7f1f0d76dd6 1572
XinZhangMS 0:f7f1f0d76dd6 1573 transfer_frame_payload_count = (uint32_t)(temp_current_payload_index - current_payload_index + 1);
XinZhangMS 0:f7f1f0d76dd6 1574 transfer_frame_payloads = (PAYLOAD*)malloc(transfer_frame_payload_count * sizeof(PAYLOAD));
XinZhangMS 0:f7f1f0d76dd6 1575 if (transfer_frame_payloads == NULL)
XinZhangMS 0:f7f1f0d76dd6 1576 {
XinZhangMS 0:f7f1f0d76dd6 1577 amqpvalue_destroy(multi_transfer_amqp_value);
XinZhangMS 0:f7f1f0d76dd6 1578 break;
XinZhangMS 0:f7f1f0d76dd6 1579 }
XinZhangMS 0:f7f1f0d76dd6 1580
XinZhangMS 0:f7f1f0d76dd6 1581 /* copy data */
XinZhangMS 0:f7f1f0d76dd6 1582 byte_counter = current_transfer_frame_payload_size;
XinZhangMS 0:f7f1f0d76dd6 1583 transfer_frame_payload_count = 0;
XinZhangMS 0:f7f1f0d76dd6 1584
XinZhangMS 0:f7f1f0d76dd6 1585 while (byte_counter > 0)
XinZhangMS 0:f7f1f0d76dd6 1586 {
XinZhangMS 0:f7f1f0d76dd6 1587 if (payloads[current_payload_index].length - current_payload_pos > byte_counter)
XinZhangMS 0:f7f1f0d76dd6 1588 {
XinZhangMS 0:f7f1f0d76dd6 1589 /* more data than we need */
XinZhangMS 0:f7f1f0d76dd6 1590 transfer_frame_payloads[transfer_frame_payload_count].bytes = payloads[current_payload_index].bytes + current_payload_pos;
XinZhangMS 0:f7f1f0d76dd6 1591 transfer_frame_payloads[transfer_frame_payload_count].length = byte_counter;
XinZhangMS 0:f7f1f0d76dd6 1592 current_payload_pos += byte_counter;
XinZhangMS 0:f7f1f0d76dd6 1593 byte_counter = 0;
XinZhangMS 0:f7f1f0d76dd6 1594 }
XinZhangMS 0:f7f1f0d76dd6 1595 else
XinZhangMS 0:f7f1f0d76dd6 1596 {
XinZhangMS 0:f7f1f0d76dd6 1597 /* copy entire payload and move to the next */
XinZhangMS 0:f7f1f0d76dd6 1598 transfer_frame_payloads[transfer_frame_payload_count].bytes = payloads[current_payload_index].bytes + current_payload_pos;
XinZhangMS 0:f7f1f0d76dd6 1599 transfer_frame_payloads[transfer_frame_payload_count].length = payloads[current_payload_index].length - current_payload_pos;
XinZhangMS 0:f7f1f0d76dd6 1600 byte_counter -= (uint32_t)payloads[current_payload_index].length - current_payload_pos;
XinZhangMS 0:f7f1f0d76dd6 1601 current_payload_index++;
XinZhangMS 0:f7f1f0d76dd6 1602 current_payload_pos = 0;
XinZhangMS 0:f7f1f0d76dd6 1603 }
XinZhangMS 0:f7f1f0d76dd6 1604
XinZhangMS 0:f7f1f0d76dd6 1605 transfer_frame_payload_count++;
XinZhangMS 0:f7f1f0d76dd6 1606 }
XinZhangMS 0:f7f1f0d76dd6 1607
XinZhangMS 0:f7f1f0d76dd6 1608 if (connection_encode_frame(session_instance->endpoint, multi_transfer_amqp_value, transfer_frame_payloads, transfer_frame_payload_count, on_send_complete, callback_context) != 0)
XinZhangMS 0:f7f1f0d76dd6 1609 {
XinZhangMS 0:f7f1f0d76dd6 1610 free(transfer_frame_payloads);
XinZhangMS 0:f7f1f0d76dd6 1611 amqpvalue_destroy(multi_transfer_amqp_value);
XinZhangMS 0:f7f1f0d76dd6 1612 break;
XinZhangMS 0:f7f1f0d76dd6 1613 }
XinZhangMS 0:f7f1f0d76dd6 1614
XinZhangMS 0:f7f1f0d76dd6 1615 free(transfer_frame_payloads);
XinZhangMS 0:f7f1f0d76dd6 1616 amqpvalue_destroy(multi_transfer_amqp_value);
XinZhangMS 0:f7f1f0d76dd6 1617 payload_size -= current_transfer_frame_payload_size;
XinZhangMS 0:f7f1f0d76dd6 1618 }
XinZhangMS 0:f7f1f0d76dd6 1619
XinZhangMS 0:f7f1f0d76dd6 1620 if (payload_size > 0)
XinZhangMS 0:f7f1f0d76dd6 1621 {
XinZhangMS 0:f7f1f0d76dd6 1622 result = SESSION_SEND_TRANSFER_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1623 }
XinZhangMS 0:f7f1f0d76dd6 1624 else
XinZhangMS 0:f7f1f0d76dd6 1625 {
XinZhangMS 0:f7f1f0d76dd6 1626 /* Codes_S_R_S_SESSION_01_018: [is incremented after each successive transfer according to RFC-1982 [RFC1982] serial number arithmetic.] */
XinZhangMS 0:f7f1f0d76dd6 1627 session_instance->next_outgoing_id++;
XinZhangMS 0:f7f1f0d76dd6 1628 session_instance->remote_incoming_window--;
XinZhangMS 0:f7f1f0d76dd6 1629 session_instance->outgoing_window--;
XinZhangMS 0:f7f1f0d76dd6 1630
XinZhangMS 0:f7f1f0d76dd6 1631 result = SESSION_SEND_TRANSFER_OK;
XinZhangMS 0:f7f1f0d76dd6 1632 }
XinZhangMS 0:f7f1f0d76dd6 1633 }
XinZhangMS 0:f7f1f0d76dd6 1634 }
XinZhangMS 0:f7f1f0d76dd6 1635
XinZhangMS 0:f7f1f0d76dd6 1636 amqpvalue_destroy(transfer_value);
XinZhangMS 0:f7f1f0d76dd6 1637 }
XinZhangMS 0:f7f1f0d76dd6 1638 }
XinZhangMS 0:f7f1f0d76dd6 1639 }
XinZhangMS 0:f7f1f0d76dd6 1640 }
XinZhangMS 0:f7f1f0d76dd6 1641 }
XinZhangMS 0:f7f1f0d76dd6 1642 }
XinZhangMS 0:f7f1f0d76dd6 1643
XinZhangMS 0:f7f1f0d76dd6 1644 return result;
XinZhangMS 0:f7f1f0d76dd6 1645 }