Azure IoT / azure_uamqp_c

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Files at this revision

API Documentation at this revision

Comitter:
AzureIoTClient
Date:
Mon Jun 11 15:39:52 2018 -0700
Parent:
42:e2c1c1b77f13
Child:
44:9dd558f13109
Commit message:
1.2.5

Changed in this revision

amqp_definitions.c Show annotated file Show diff for this revision Revisions of this file
amqp_frame_codec.c Show annotated file Show diff for this revision Revisions of this file
amqp_management.c Show annotated file Show diff for this revision Revisions of this file
amqpvalue.c Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_accepted.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_address_string.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_amqp_error.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_amqp_sequence.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_amqp_value.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_annotations.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_application_properties.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_attach.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_begin.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_close.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_connection_error.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_data.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_delivery_annotations.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_delivery_number.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_delivery_tag.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_detach.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_disposition.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_end.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_error.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_fields.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_filter_set.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_flow.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_footer.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_handle.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_header.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_ietf_language_tag.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_link_error.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_message_annotations.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_message_format.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_message_id_binary.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_message_id_string.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_message_id_ulong.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_message_id_uuid.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_milliseconds.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_modified.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_node_properties.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_open.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_properties.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_received.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_receiver_settle_mode.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_rejected.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_released.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_role.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_sasl_challenge.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_sasl_code.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_sasl_init.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_sasl_mechanisms.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_sasl_outcome.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_sasl_response.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_seconds.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_sender_settle_mode.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_sequence_no.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_session_error.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_source.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_target.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_terminus_durability.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_terminus_expiry_policy.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_transfer.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_definitions_transfer_number.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqp_frame_codec.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/amqpvalue.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/connection.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/header_detect_io.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/link.h Show annotated file Show diff for this revision Revisions of this file
azure_uamqp_c/sasl_frame_codec.h Show annotated file Show diff for this revision Revisions of this file
connection.c Show annotated file Show diff for this revision Revisions of this file
header_detect_io.c Show annotated file Show diff for this revision Revisions of this file
link.c Show annotated file Show diff for this revision Revisions of this file
message_receiver.c Show annotated file Show diff for this revision Revisions of this file
message_sender.c Show annotated file Show diff for this revision Revisions of this file
saslclientio.c Show annotated file Show diff for this revision Revisions of this file
session.c Show annotated file Show diff for this revision Revisions of this file
--- a/amqp_definitions.c	Fri May 04 13:24:52 2018 -0700
+++ b/amqp_definitions.c	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #include <stdlib.h>
 #include "azure_c_shared_utility/optimize_size.h"
 #include "azure_c_shared_utility/gballoc.h"
@@ -382,8 +385,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_symbol(item_value, condition_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_symbol(item_value, condition_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -465,8 +468,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_string(item_value, description_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_string(item_value, description_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -548,8 +551,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_fields(item_value, info_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_fields(item_value, info_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -1119,8 +1122,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_string(item_value, container_id_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_string(item_value, container_id_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -1202,8 +1205,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_string(item_value, hostname_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_string(item_value, hostname_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -1287,8 +1290,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_uint(item_value, max_frame_size_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_uint(item_value, max_frame_size_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -1380,8 +1383,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_ushort(item_value, channel_max_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_ushort(item_value, channel_max_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -1471,8 +1474,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_milliseconds(item_value, idle_time_out_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_milliseconds(item_value, idle_time_out_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -2142,8 +2145,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_fields(item_value, properties_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_fields(item_value, properties_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -2659,8 +2662,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_ushort(item_value, remote_channel_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_ushort(item_value, remote_channel_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -2742,8 +2745,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_transfer_number(item_value, next_outgoing_id_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_transfer_number(item_value, next_outgoing_id_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -2825,8 +2828,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_uint(item_value, incoming_window_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_uint(item_value, incoming_window_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -2908,8 +2911,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_uint(item_value, outgoing_window_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_uint(item_value, outgoing_window_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -2993,8 +2996,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_handle(item_value, handle_max_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_handle(item_value, handle_max_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -3378,8 +3381,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_fields(item_value, properties_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_fields(item_value, properties_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -4037,8 +4040,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_string(item_value, name_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_string(item_value, name_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -4120,8 +4123,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_handle(item_value, handle_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_handle(item_value, handle_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -4203,8 +4206,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_role(item_value, role_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_role(item_value, role_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -4288,8 +4291,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_sender_settle_mode(item_value, snd_settle_mode_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_sender_settle_mode(item_value, snd_settle_mode_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -4381,8 +4384,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_receiver_settle_mode(item_value, rcv_settle_mode_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_receiver_settle_mode(item_value, rcv_settle_mode_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -4640,8 +4643,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_map(item_value, unsettled_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_map(item_value, unsettled_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -4733,8 +4736,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_boolean(item_value, incomplete_unsettled_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_boolean(item_value, incomplete_unsettled_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -4824,8 +4827,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_sequence_no(item_value, initial_delivery_count_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_sequence_no(item_value, initial_delivery_count_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -4907,8 +4910,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_ulong(item_value, max_message_size_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_ulong(item_value, max_message_size_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -5284,8 +5287,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_fields(item_value, properties_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_fields(item_value, properties_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -5884,8 +5887,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_transfer_number(item_value, next_incoming_id_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_transfer_number(item_value, next_incoming_id_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -5967,8 +5970,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_uint(item_value, incoming_window_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_uint(item_value, incoming_window_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -6050,8 +6053,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_transfer_number(item_value, next_outgoing_id_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_transfer_number(item_value, next_outgoing_id_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -6133,8 +6136,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_uint(item_value, outgoing_window_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_uint(item_value, outgoing_window_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -6216,8 +6219,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_handle(item_value, handle_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_handle(item_value, handle_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -6299,8 +6302,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_sequence_no(item_value, delivery_count_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_sequence_no(item_value, delivery_count_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -6382,8 +6385,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_uint(item_value, link_credit_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_uint(item_value, link_credit_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -6465,8 +6468,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_uint(item_value, available_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_uint(item_value, available_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -6550,8 +6553,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_boolean(item_value, drain_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_boolean(item_value, drain_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -6643,8 +6646,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_boolean(item_value, echo_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_boolean(item_value, echo_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -6734,8 +6737,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_fields(item_value, properties_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_fields(item_value, properties_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -7282,8 +7285,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_handle(item_value, handle_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_handle(item_value, handle_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -7365,8 +7368,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_delivery_number(item_value, delivery_id_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_delivery_number(item_value, delivery_id_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -7448,8 +7451,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_delivery_tag(item_value, delivery_tag_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_delivery_tag(item_value, delivery_tag_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -7531,8 +7534,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_message_format(item_value, message_format_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_message_format(item_value, message_format_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -7614,8 +7617,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_boolean(item_value, settled_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_boolean(item_value, settled_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -7699,8 +7702,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_boolean(item_value, more_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_boolean(item_value, more_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -7790,8 +7793,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_receiver_settle_mode(item_value, rcv_settle_mode_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_receiver_settle_mode(item_value, rcv_settle_mode_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -7959,8 +7962,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_boolean(item_value, resume_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_boolean(item_value, resume_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -8052,8 +8055,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_boolean(item_value, aborted_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_boolean(item_value, aborted_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -8145,8 +8148,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_boolean(item_value, batchable_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_boolean(item_value, batchable_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -8574,8 +8577,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_role(item_value, role_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_role(item_value, role_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -8657,8 +8660,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_delivery_number(item_value, first_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_delivery_number(item_value, first_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -8740,8 +8743,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_delivery_number(item_value, last_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_delivery_number(item_value, last_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -8825,8 +8828,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_boolean(item_value, settled_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_boolean(item_value, settled_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -9002,8 +9005,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_boolean(item_value, batchable_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_boolean(item_value, batchable_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -9346,8 +9349,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_handle(item_value, handle_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_handle(item_value, handle_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -9431,8 +9434,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_boolean(item_value, closed_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_boolean(item_value, closed_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -9522,8 +9525,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_error(item_value, error_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_error(item_value, error_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -9776,8 +9779,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_error(item_value, error_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_error(item_value, error_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -10030,8 +10033,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_error(item_value, error_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_error(item_value, error_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -10709,8 +10712,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_symbol(item_value, mechanism_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_symbol(item_value, mechanism_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -10792,8 +10795,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_binary(item_value, initial_response_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_binary(item_value, initial_response_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -10875,8 +10878,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_string(item_value, hostname_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_string(item_value, hostname_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -11149,8 +11152,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_binary(item_value, challenge_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_binary(item_value, challenge_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -11423,8 +11426,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_binary(item_value, response_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_binary(item_value, response_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -11726,8 +11729,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_sasl_code(item_value, code_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_sasl_code(item_value, code_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -11809,8 +11812,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_binary(item_value, additional_data_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_binary(item_value, additional_data_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -12435,8 +12438,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_terminus_durability(item_value, durable_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_terminus_durability(item_value, durable_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -12528,8 +12531,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_terminus_expiry_policy(item_value, expiry_policy_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_terminus_expiry_policy(item_value, expiry_policy_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -12621,8 +12624,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_seconds(item_value, timeout_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_seconds(item_value, timeout_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -12714,8 +12717,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_boolean(item_value, dynamic_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_boolean(item_value, dynamic_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -12805,8 +12808,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_node_properties(item_value, dynamic_node_properties_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_node_properties(item_value, dynamic_node_properties_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -12888,8 +12891,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_symbol(item_value, distribution_mode_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_symbol(item_value, distribution_mode_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -12971,8 +12974,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_filter_set(item_value, filter_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_filter_set(item_value, filter_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -13845,8 +13848,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_terminus_durability(item_value, durable_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_terminus_durability(item_value, durable_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -13938,8 +13941,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_terminus_expiry_policy(item_value, expiry_policy_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_terminus_expiry_policy(item_value, expiry_policy_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -14031,8 +14034,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_seconds(item_value, timeout_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_seconds(item_value, timeout_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -14124,8 +14127,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_boolean(item_value, dynamic_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_boolean(item_value, dynamic_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -14215,8 +14218,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_node_properties(item_value, dynamic_node_properties_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_node_properties(item_value, dynamic_node_properties_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -14772,8 +14775,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_boolean(item_value, durable_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_boolean(item_value, durable_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -14865,8 +14868,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_ubyte(item_value, priority_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_ubyte(item_value, priority_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -14956,8 +14959,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_milliseconds(item_value, ttl_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_milliseconds(item_value, ttl_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -15041,8 +15044,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_boolean(item_value, first_acquirer_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_boolean(item_value, first_acquirer_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -15134,8 +15137,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_uint(item_value, delivery_count_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_uint(item_value, delivery_count_value);
+                    if (get_single_value_result != 0)
                     {
                         if (amqpvalue_get_type(item_value) != AMQP_TYPE_NULL)
                         {
@@ -16096,8 +16099,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_binary(item_value, user_id_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_binary(item_value, user_id_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -16263,8 +16266,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_string(item_value, subject_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_string(item_value, subject_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -16514,8 +16517,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_symbol(item_value, content_type_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_symbol(item_value, content_type_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -16597,8 +16600,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_symbol(item_value, content_encoding_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_symbol(item_value, content_encoding_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -16680,8 +16683,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_timestamp(item_value, absolute_expiry_time_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_timestamp(item_value, absolute_expiry_time_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -16763,8 +16766,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_timestamp(item_value, creation_time_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_timestamp(item_value, creation_time_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -16846,8 +16849,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_string(item_value, group_id_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_string(item_value, group_id_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -16929,8 +16932,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_sequence_no(item_value, group_sequence_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_sequence_no(item_value, group_sequence_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -17012,8 +17015,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_string(item_value, reply_to_group_id_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_string(item_value, reply_to_group_id_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -17333,8 +17336,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_uint(item_value, section_number_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_uint(item_value, section_number_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -17416,8 +17419,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_ulong(item_value, section_offset_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_ulong(item_value, section_offset_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -17807,8 +17810,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_error(item_value, error_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_error(item_value, error_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -18252,8 +18255,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_boolean(item_value, delivery_failed_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_boolean(item_value, delivery_failed_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -18335,8 +18338,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_boolean(item_value, undeliverable_here_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_boolean(item_value, undeliverable_here_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
@@ -18418,8 +18421,8 @@
                 }
                 else
                 {
-                    int get_single_value_result;
-                    if ((get_single_value_result = amqpvalue_get_fields(item_value, message_annotations_value)) != 0)
+                    int get_single_value_result = amqpvalue_get_fields(item_value, message_annotations_value);
+                    if (get_single_value_result != 0)
                     {
                         result = __FAILURE__;
                     }
--- a/amqp_frame_codec.c	Fri May 04 13:24:52 2018 -0700
+++ b/amqp_frame_codec.c	Mon Jun 11 15:39:52 2018 -0700
@@ -18,7 +18,7 @@
     AMQP_FRAME_DECODE_ERROR
 } AMQP_FRAME_DECODE_STATE;
 
-typedef struct AMQP_FRAME_CODEC_INSTANCE_TAG
+typedef struct AMQP_FRAME_CODEC_TAG
 {
     FRAME_CODEC_HANDLE frame_codec;
 
@@ -30,11 +30,11 @@
     AMQPVALUE_DECODER_HANDLE decoder;
     AMQP_FRAME_DECODE_STATE decode_state;
     AMQP_VALUE decoded_performative;
-} AMQP_FRAME_CODEC_INSTANCE;
+} AMQP_FRAME_CODEC;
 
 static void amqp_value_decoded(void* context, AMQP_VALUE decoded_value)
 {
-    AMQP_FRAME_CODEC_INSTANCE* amqp_frame_codec_instance = (AMQP_FRAME_CODEC_INSTANCE*)context;
+    AMQP_FRAME_CODEC_HANDLE amqp_frame_codec = (AMQP_FRAME_CODEC_HANDLE)context;
     uint64_t performative_descriptor_ulong;
     AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(decoded_value);
 
@@ -46,20 +46,20 @@
         (performative_descriptor_ulong > AMQP_CLOSE))
     {
         /* Codes_SRS_AMQP_FRAME_CODEC_01_060: [If any error occurs while decoding a frame, the decoder shall switch to an error state where decoding shall not be possible anymore.] */
-        amqp_frame_codec_instance->decode_state = AMQP_FRAME_DECODE_ERROR;
+        amqp_frame_codec->decode_state = AMQP_FRAME_DECODE_ERROR;
     }
     else
     {
-        amqp_frame_codec_instance->decoded_performative = decoded_value;
+        amqp_frame_codec->decoded_performative = decoded_value;
     }
 }
 
 static void frame_received(void* context, const unsigned char* type_specific, uint32_t type_specific_size, const unsigned char* frame_body, uint32_t frame_body_size)
 {
-    AMQP_FRAME_CODEC_INSTANCE* amqp_frame_codec_instance = (AMQP_FRAME_CODEC_INSTANCE*)context;
+    AMQP_FRAME_CODEC_HANDLE amqp_frame_codec = (AMQP_FRAME_CODEC_HANDLE)context;
     uint16_t channel;
 
-    switch (amqp_frame_codec_instance->decode_state)
+    switch (amqp_frame_codec->decode_state)
     {
     default:
     /* Codes_SRS_AMQP_FRAME_CODEC_01_050: [All subsequent decoding shall fail and no AMQP frames shall be indicated from that point on to the consumers of amqp_frame_codec.] */
@@ -70,10 +70,10 @@
         /* Codes_SRS_AMQP_FRAME_CODEC_01_049: [If not enough type specific bytes are received to decode the channel number, the decoding shall stop with an error.] */
         if (type_specific_size < 2)
         {
-            amqp_frame_codec_instance->decode_state = AMQP_FRAME_DECODE_ERROR;
+            amqp_frame_codec->decode_state = AMQP_FRAME_DECODE_ERROR;
 
             /* Codes_SRS_AMQP_FRAME_CODEC_01_069: [If any error occurs while decoding a frame, the decoder shall indicate the error by calling the amqp_frame_codec_error_callback  and passing to it the callback context argument that was given in amqp_frame_codec_create.] */
-            amqp_frame_codec_instance->error_callback(amqp_frame_codec_instance->callback_context);
+            amqp_frame_codec->error_callback(amqp_frame_codec->callback_context);
         }
         else
         {
@@ -85,23 +85,23 @@
             {
                 /* Codes_SRS_AMQP_FRAME_CODEC_01_048: [When a frame header is received from frame_codec and the frame payload size is 0, empty_frame_received_callback shall be invoked, while passing the channel number as argument.] */
                 /* Codes_SRS_AMQP_FRAME_CODEC_01_007: [An AMQP frame with no body MAY be used to generate artificial traffic as needed to satisfy any negotiated idle timeout interval ] */
-                amqp_frame_codec_instance->empty_frame_received_callback(amqp_frame_codec_instance->callback_context, channel);
+                amqp_frame_codec->empty_frame_received_callback(amqp_frame_codec->callback_context, channel);
             }
             else
             {
                 /* Codes_SRS_AMQP_FRAME_CODEC_01_051: [If the frame payload is greater than 0, amqp_frame_codec shall decode the performative as a described AMQP type.] */
                 /* Codes_SRS_AMQP_FRAME_CODEC_01_002: [The frame body is defined as a performative followed by an opaque payload.] */
-                amqp_frame_codec_instance->decoded_performative = NULL;
+                amqp_frame_codec->decoded_performative = NULL;
 
                 while ((frame_body_size > 0) &&
-                       (amqp_frame_codec_instance->decoded_performative == NULL) &&
-                       (amqp_frame_codec_instance->decode_state != AMQP_FRAME_DECODE_ERROR))
+                       (amqp_frame_codec->decoded_performative == NULL) &&
+                       (amqp_frame_codec->decode_state != AMQP_FRAME_DECODE_ERROR))
                 {
                     /* Codes_SRS_AMQP_FRAME_CODEC_01_052: [Decoding the performative shall be done by feeding the bytes to the decoder create in amqp_frame_codec_create.] */
-                    if (amqpvalue_decode_bytes(amqp_frame_codec_instance->decoder, frame_body, 1) != 0)
+                    if (amqpvalue_decode_bytes(amqp_frame_codec->decoder, frame_body, 1) != 0)
                     {
                         /* Codes_SRS_AMQP_FRAME_CODEC_01_060: [If any error occurs while decoding a frame, the decoder shall switch to an error state where decoding shall not be possible anymore.] */
-                        amqp_frame_codec_instance->decode_state = AMQP_FRAME_DECODE_ERROR;
+                        amqp_frame_codec->decode_state = AMQP_FRAME_DECODE_ERROR;
                     }
                     else
                     {
@@ -110,10 +110,10 @@
                     }
                 }
 
-                if (amqp_frame_codec_instance->decode_state == AMQP_FRAME_DECODE_ERROR)
+                if (amqp_frame_codec->decode_state == AMQP_FRAME_DECODE_ERROR)
                 {
                     /* Codes_SRS_AMQP_FRAME_CODEC_01_069: [If any error occurs while decoding a frame, the decoder shall indicate the error by calling the amqp_frame_codec_error_callback  and passing to it the callback context argument that was given in amqp_frame_codec_create.] */
-                    amqp_frame_codec_instance->error_callback(amqp_frame_codec_instance->callback_context);
+                    amqp_frame_codec->error_callback(amqp_frame_codec->callback_context);
                 }
                 else
                 {
@@ -121,7 +121,7 @@
                     /* Codes_SRS_AMQP_FRAME_CODEC_01_067: [When the performative is decoded, the rest of the frame_bytes shall not be given to the AMQP decoder, but they shall be buffered so that later they are given to the frame_received callback.] */
                     /* Codes_SRS_AMQP_FRAME_CODEC_01_054: [Once the performative is decoded and all frame payload bytes are received, the callback frame_received_callback shall be called.] */
                     /* Codes_SRS_AMQP_FRAME_CODEC_01_068: [A pointer to all the payload bytes shall also be passed to frame_received_callback.] */
-                    amqp_frame_codec_instance->frame_received_callback(amqp_frame_codec_instance->callback_context, channel, amqp_frame_codec_instance->decoded_performative, frame_body, frame_body_size);
+                    amqp_frame_codec->frame_received_callback(amqp_frame_codec->callback_context, channel, amqp_frame_codec->decoded_performative, frame_body, frame_body_size);
                 }
             }
         }
@@ -141,7 +141,7 @@
 AMQP_FRAME_CODEC_HANDLE amqp_frame_codec_create(FRAME_CODEC_HANDLE frame_codec, AMQP_FRAME_RECEIVED_CALLBACK frame_received_callback,
     AMQP_EMPTY_FRAME_RECEIVED_CALLBACK empty_frame_received_callback, AMQP_FRAME_CODEC_ERROR_CALLBACK amqp_frame_codec_error_callback, void* callback_context)
 {
-    AMQP_FRAME_CODEC_INSTANCE* result;
+    AMQP_FRAME_CODEC_HANDLE result;
 
     /* Codes_SRS_AMQP_FRAME_CODEC_01_012: [If any of the arguments frame_codec, frame_received_callback, amqp_frame_codec_error_callback or empty_frame_received_callback is NULL, amqp_frame_codec_create shall return NULL.] */
     if ((frame_codec == NULL) ||
@@ -155,7 +155,7 @@
     }
     else
     {
-        result = (AMQP_FRAME_CODEC_INSTANCE*)malloc(sizeof(AMQP_FRAME_CODEC_INSTANCE));
+        result = (AMQP_FRAME_CODEC_HANDLE)malloc(sizeof(AMQP_FRAME_CODEC));
         /* Codes_SRS_AMQP_FRAME_CODEC_01_020: [If allocating memory for the new amqp_frame_codec fails, then amqp_frame_codec_create shall fail and return NULL.] */
         if (result == NULL)
         {
--- a/amqp_management.c	Fri May 04 13:24:52 2018 -0700
+++ b/amqp_management.c	Mon Jun 11 15:39:52 2018 -0700
@@ -54,8 +54,8 @@
     AMQP_MANAGEMENT_STATE amqp_management_state;
     char* status_code_key_name;
     char* status_description_key_name;
-    int sender_connected : 1;
-    int receiver_connected : 1;
+    unsigned int sender_connected : 1;
+    unsigned int receiver_connected : 1;
 } AMQP_MANAGEMENT_INSTANCE;
 
 static AMQP_VALUE on_message_received(const void* context, MESSAGE_HANDLE message)
@@ -410,7 +410,7 @@
                     break;
 
                 case MESSAGE_SENDER_STATE_OPEN:
-                    amqp_management_instance->sender_connected = -1;
+                    amqp_management_instance->sender_connected = 1;
                     /* Codes_SRS_AMQP_MANAGEMENT_01_142: [ - If `new_state` is `MESSAGE_SENDER_STATE_OPEN` and the message receiver did not yet indicate its state as `MESSAGE_RECEIVER_STATE_OPEN`, the `on_amqp_management_open_complete` callback shall not be called.]*/
                     if (amqp_management_instance->receiver_connected != 0)
                     {
@@ -509,7 +509,7 @@
                     break;
 
                 case MESSAGE_RECEIVER_STATE_OPEN:
-                    amqp_management_instance->receiver_connected = -1;
+                    amqp_management_instance->receiver_connected = 1;
                     /* Codes_SRS_AMQP_MANAGEMENT_01_154: [ - If `new_state` is `MESSAGE_RECEIVER_STATE_OPEN` and the message sender did not yet indicate its state as `MESSAGE_RECEIVER_STATE_OPEN`, the `on_amqp_management_open_complete` callback shall not be called. ]*/
                     if (amqp_management_instance->sender_connected != 0)
                     {
@@ -1062,7 +1062,7 @@
                     operation_message->on_execute_operation_complete(operation_message->callback_context, AMQP_MANAGEMENT_EXECUTE_OPERATION_INSTANCE_CLOSED, 0, NULL, NULL);
                     free(operation_message);
                 }
-                
+
                 if (singlylinkedlist_remove(amqp_management->pending_operations, list_item_handle) != 0)
                 {
                     LogError("Cannot remove item");
--- a/amqpvalue.c	Fri May 04 13:24:52 2018 -0700
+++ b/amqpvalue.c	Mon Jun 11 15:39:52 2018 -0700
@@ -1799,16 +1799,21 @@
     return result;
 }
 
+/* Codes_SRS_AMQPVALUE_01_397: [1.6.24 array A sequence of values of a single type.] */
 AMQP_VALUE amqpvalue_create_array(void)
 {
     AMQP_VALUE result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA);
     if (result == NULL)
     {
+        /* Codes_SRS_AMQPVALUE_01_405: [ If allocating memory for the array fails, then `amqpvalue_create_array` shall return NULL. ] */
         LogError("Could not allocate memory for AMQP value");
     }
     else
     {
+        /* Codes_SRS_AMQPVALUE_01_404: [ `amqpvalue_create_array` shall return a handle to an AMQP_VALUE that stores an array. ] */
         result->type = AMQP_TYPE_ARRAY;
+
+        /* Codes_SRS_AMQPVALUE_01_406: [ The array shall have an initial size of zero. ] */
         result->value.array_value.items = NULL;
         result->value.array_value.count = 0;
     }
@@ -1816,21 +1821,23 @@
     return result;
 }
 
-int amqpvalue_get_array_item_count(AMQP_VALUE value, uint32_t* size)
+int amqpvalue_get_array_item_count(AMQP_VALUE value, uint32_t* count)
 {
     int result;
 
+    /* Tests_SRS_AMQPVALUE_01_421: [ If any of the arguments is NULL, `amqpvalue_get_array_item_count` shall fail and return a non-zero value. ]*/
     if ((value == NULL) ||
-        (size == NULL))
-    {
-        LogError("Bad arguments: value = %p, size = %p",
-            value, size);
+        (count == NULL))
+    {
+        LogError("Bad arguments: value = %p, count = %p",
+            value, count);
         result = __FAILURE__;
     }
     else
     {
         AMQP_VALUE_DATA* value_data = (AMQP_VALUE_DATA*)value;
 
+        /* Codes_SRS_AMQPVALUE_01_422: [ If the array argument is not an AMQP value created with the `amqpvalue_create_array` function then `amqpvalue_get_array_item_count` shall fail and return a non-zero value. ]*/
         if (value_data->type != AMQP_TYPE_ARRAY)
         {
             LogError("Value is not of type ARRAY");
@@ -1838,7 +1845,10 @@
         }
         else
         {
-            *size = value_data->value.array_value.count;
+            /* Codes_SRS_AMQPVALUE_01_419: [ `amqpvalue_get_array_item_count` shall return in `count` the number of items in the array. ]*/
+            *count = value_data->value.array_value.count;
+
+            /* Codes_SRS_AMQPVALUE_01_420: [ On success `amqpvalue_get_array_item_count` shall return 0. ]*/
             result = 0;
         }
     }
@@ -1850,6 +1860,7 @@
 {
     int result;
 
+    /* Codes_SRS_AMQPVALUE_01_409: [ If `value` or `array_item_value` is NULL, amqpvalue_add_array_item shall fail and return a non-zero value. ]*/
     if (value == NULL)
     {
         LogError("NULL value");
@@ -1857,6 +1868,7 @@
     }
     else
     {
+        /* Codes_SRS_AMQPVALUE_01_413: [ If the `value` argument is not an AMQP array created with the `amqpvalue_create_array` function than `amqpvalue_add_array_item` shall fail and return a non-zero value. ] */
         AMQP_VALUE_DATA* value_data = (AMQP_VALUE_DATA*)value;
         if (value_data->type != AMQP_TYPE_ARRAY)
         {
@@ -1865,6 +1877,7 @@
         }
         else
         {
+            /* Codes_SRS_AMQPVALUE_01_425: [ If the type of `array_item_value` does not match that of items already in the array then `amqpvalue_add_array_item` shall fail and return a non-zero value. ] */
             AMQP_VALUE_DATA* array_item_value_data = (AMQP_VALUE_DATA*)array_item_value;
             if ((value_data->value.array_value.count > 0) &&
                 (array_item_value_data->type != value_data->value.array_value.items[0]->type))
@@ -1874,9 +1887,12 @@
             }
             else
             {
+                /* Codes_SRS_AMQPVALUE_01_410: [ The item stored at the n-th position in the array shall be a clone of `array_item_value`. ] */
                 AMQP_VALUE cloned_item = amqpvalue_clone(array_item_value);
                 if (cloned_item == NULL)
                 {
+                    /* Codes_SRS_AMQPVALUE_01_423: [ When `amqpvalue_add_array_item` fails due to not being able to clone the item or grow the array, the array shall not be altered. ] */
+                    /* Codes_SRS_AMQPVALUE_01_412: [ If cloning the item fails, `amqpvalue_add_array_item` shall fail and return a non-zero value. ]*/
                     LogError("Cannot clone value to put in the array");
                     result = __FAILURE__;
                 }
@@ -1885,6 +1901,8 @@
                     AMQP_VALUE* new_array = (AMQP_VALUE*)realloc(value_data->value.array_value.items, (value_data->value.array_value.count + 1) * sizeof(AMQP_VALUE));
                     if (new_array == NULL)
                     {
+                        /* Codes_SRS_AMQPVALUE_01_423: [ When `amqpvalue_add_array_item` fails due to not being able to clone the item or grow the array, the array shall not be altered. ] */
+                        /* Codes_SRS_AMQPVALUE_01_424: [ If growing the array fails, then `amqpvalue_add_array_item` shall fail and return a non-zero value. ] */
                         amqpvalue_destroy(cloned_item);
                         LogError("Cannot resize array");
                         result = __FAILURE__;
@@ -1893,9 +1911,11 @@
                     {
                         value_data->value.array_value.items = new_array;
 
+                        /* Codes_SRS_AMQPVALUE_01_407: [ `amqpvalue_add_array_item` shall add the AMQP_VALUE specified by `array_item_value` at the 0 based n-th position in the array. ]*/
                         value_data->value.array_value.items[value_data->value.array_value.count] = cloned_item;
                         value_data->value.array_value.count++;
 
+                        /* Codes_SRS_AMQPVALUE_01_408: [ On success `amqpvalue_add_array_item` shall return 0. ]*/
                         result = 0;
                     }
                 }
@@ -1912,6 +1932,7 @@
 
     if (value == NULL)
     {
+        /* Codes_SRS_AMQPVALUE_01_416: [ If the `value` argument is NULL, `amqpvalue_get_array_item` shall fail and return NULL. ] */
         LogError("NULL value");
         result = NULL;
     }
@@ -1919,11 +1940,13 @@
     {
         AMQP_VALUE_DATA* value_data = (AMQP_VALUE_DATA*)value;
 
+        /* Codes_SRS_AMQPVALUE_01_418: [ If value is not an array then `amqpvalue_get_array_item` shall fail and return NULL. ] */
         if (value_data->type != AMQP_TYPE_ARRAY)
         {
             LogError("Value is not of type ARRAY");
             result = NULL;
         }
+        /* Codes_SRS_AMQPVALUE_01_417: [ If `index` is greater or equal to the number of items in the array then `amqpvalue_get_array_item` shall fail and return NULL. ] */
         else if (value_data->value.array_value.count <= index)
         {
             LogError("Index out of range: %u", (unsigned int)index);
@@ -1931,6 +1954,8 @@
         }
         else
         {
+            /* Codes_SRS_AMQPVALUE_01_414: [ `amqpvalue_get_array_item` shall return a copy of the AMQP_VALUE stored at the 0 based position `index` in the array identified by `value`. ] */
+            /* Codes_SRS_AMQPVALUE_01_426: [ If cloning the item at position `index` fails, then `amqpvalue_get_array_item` shall fail and return NULL. ] */
             result = amqpvalue_clone(value_data->value.array_value.items[index]);
         }
     }
@@ -2122,6 +2147,31 @@
 
                 break;
             }
+            case AMQP_TYPE_ARRAY:
+            {
+                /* Codes_SRS_AMQPVALUE_01_427: [- array: compare array item count and each element. ] */
+                if (value1_data->value.array_value.count != value2_data->value.array_value.count)
+                {
+                    result = false;
+                }
+                else
+                {
+                    uint32_t i;
+
+                    for (i = 0; i < value1_data->value.array_value.count; i++)
+                    {
+                        /* Codes_SRS_AMQPVALUE_01_428: [ Nesting shall be considered in comparison. ] */
+                        if (!amqpvalue_are_equal(value1_data->value.array_value.items[i], value2_data->value.array_value.items[i]))
+                        {
+                            break;
+                        }
+                    }
+
+                    result = (i == value1_data->value.array_value.count);
+                }
+
+                break;
+            }
             case AMQP_TYPE_MAP:
             {
                 /* Codes_SRS_AMQPVALUE_01_233: [- map: compare map pair count and each key/value pair.] */
@@ -3047,6 +3097,115 @@
     return result;
 }
 
+static int encode_array(AMQPVALUE_ENCODER_OUTPUT encoder_output, void* context, uint32_t count, AMQP_VALUE* items)
+{
+    size_t i;
+    int result;
+
+    uint32_t size = 0;
+
+    /* get the size of all items in the array */
+    for (i = 0; i < count; i++)
+    {
+        size_t item_size;
+        if (amqpvalue_get_encoded_size(items[i], &item_size) != 0)
+        {
+            LogError("Could not get encoded size for element %u of the array", (unsigned int)i);
+            break;
+        }
+
+        if ((item_size > UINT32_MAX) ||
+            size + (uint32_t)item_size < size)
+        {
+            LogError("Overflow in array size computation");
+            break;
+        }
+        
+        size = (uint32_t)(size + item_size);
+
+    }
+
+    if (i < count)
+    {
+        /* Codes_SRS_AMQPVALUE_01_274: [When the encoder output function fails, amqpvalue_encode shall fail and return a non-zero value.] */
+        result = __FAILURE__;
+    }
+    else
+    {
+        if ((count <= 255) && (size < 255))
+        {
+            size++;
+
+            /* Codes_SRS_AMQPVALUE_01_306: [<encoding name="map8" code="0xE0" category="compound" width="1" label="up to 2^8 - 1 octets of encoded map data"/>] */
+            if ((output_byte(encoder_output, context, 0xE0) != 0) ||
+                /* size */
+                (output_byte(encoder_output, context, (size & 0xFF)) != 0) ||
+                /* count */
+                (output_byte(encoder_output, context, (count & 0xFF)) != 0))
+            {
+                /* Codes_SRS_AMQPVALUE_01_274: [When the encoder output function fails, amqpvalue_encode shall fail and return a non-zero value.] */
+                LogError("Could not encode map header");
+                result = __FAILURE__;
+            }
+            else
+            {
+                /* Codes_SRS_AMQPVALUE_01_266: [On success amqpvalue_encode shall return 0.] */
+                result = 0;
+            }
+        }
+        else
+        {
+            size += 4;
+
+            /* Codes_SRS_AMQPVALUE_01_307: [<encoding name="map32" code="0xF0" category="compound" width="4" label="up to 2^32 - 1 octets of encoded map data"/>] */
+            if ((output_byte(encoder_output, context, 0xF0) != 0) ||
+                /* size */
+                (output_byte(encoder_output, context, (size >> 24) & 0xFF) != 0) ||
+                (output_byte(encoder_output, context, (size >> 16) & 0xFF) != 0) ||
+                (output_byte(encoder_output, context, (size >> 8) & 0xFF) != 0) ||
+                (output_byte(encoder_output, context, size & 0xFF) != 0) ||
+                /* count */
+                (output_byte(encoder_output, context, (count >> 24) & 0xFF) != 0) ||
+                (output_byte(encoder_output, context, (count >> 16) & 0xFF) != 0) ||
+                (output_byte(encoder_output, context, (count >> 8) & 0xFF) != 0) ||
+                (output_byte(encoder_output, context, count & 0xFF) != 0))
+            {
+                /* Codes_SRS_AMQPVALUE_01_274: [When the encoder output function fails, amqpvalue_encode shall fail and return a non-zero value.] */
+                LogError("Could not encode array");
+                result = __FAILURE__;
+            }
+            else
+            {
+                /* Codes_SRS_AMQPVALUE_01_266: [On success amqpvalue_encode shall return 0.] */
+                result = 0;
+            }
+        }
+
+        if (result == 0)
+        {
+            for (i = 0; i < count; i++)
+            {
+                if (amqpvalue_encode(items[i], encoder_output, context) != 0)
+                {
+                    break;
+                }
+            }
+
+            if (i < count)
+            {
+                LogError("Failed encoding element %u of the array", (unsigned int)i);
+                result = __FAILURE__;
+            }
+            else
+            {
+                result = 0;
+            }
+        }
+    }
+
+    return result;
+}
+
 static int encode_descriptor_header(AMQPVALUE_ENCODER_OUTPUT encoder_output, void* context)
 {
     int result;
@@ -3163,6 +3322,10 @@
             result = encode_list(encoder_output, context, value_data->value.list_value.count, value_data->value.list_value.items);
             break;
 
+        case AMQP_TYPE_ARRAY:
+            result = encode_array(encoder_output, context, value_data->value.array_value.count, value_data->value.array_value.items);
+            break;
+
         case AMQP_TYPE_MAP:
             result = encode_map(encoder_output, context, value_data->value.map_value.pair_count, value_data->value.map_value.pairs);
             break;
--- a/azure_uamqp_c/amqp_definitions.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_H
 #define AMQP_DEFINITIONS_H
 
--- a/azure_uamqp_c/amqp_definitions_accepted.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_accepted.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_ACCEPTED_H
 #define AMQP_DEFINITIONS_ACCEPTED_H
 
--- a/azure_uamqp_c/amqp_definitions_address_string.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_address_string.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_ADDRESS_STRING_H
 #define AMQP_DEFINITIONS_ADDRESS_STRING_H
 
--- a/azure_uamqp_c/amqp_definitions_amqp_error.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_amqp_error.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_AMQP_ERROR_H
 #define AMQP_DEFINITIONS_AMQP_ERROR_H
 
--- a/azure_uamqp_c/amqp_definitions_amqp_sequence.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_amqp_sequence.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_AMQP_SEQUENCE_H
 #define AMQP_DEFINITIONS_AMQP_SEQUENCE_H
 
--- a/azure_uamqp_c/amqp_definitions_amqp_value.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_amqp_value.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_AMQP_VALUE_H
 #define AMQP_DEFINITIONS_AMQP_VALUE_H
 
--- a/azure_uamqp_c/amqp_definitions_annotations.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_annotations.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_ANNOTATIONS_H
 #define AMQP_DEFINITIONS_ANNOTATIONS_H
 
--- a/azure_uamqp_c/amqp_definitions_application_properties.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_application_properties.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_APPLICATION_PROPERTIES_H
 #define AMQP_DEFINITIONS_APPLICATION_PROPERTIES_H
 
--- a/azure_uamqp_c/amqp_definitions_attach.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_attach.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_ATTACH_H
 #define AMQP_DEFINITIONS_ATTACH_H
 
--- a/azure_uamqp_c/amqp_definitions_begin.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_begin.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_BEGIN_H
 #define AMQP_DEFINITIONS_BEGIN_H
 
--- a/azure_uamqp_c/amqp_definitions_close.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_close.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_CLOSE_H
 #define AMQP_DEFINITIONS_CLOSE_H
 
--- a/azure_uamqp_c/amqp_definitions_connection_error.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_connection_error.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_CONNECTION_ERROR_H
 #define AMQP_DEFINITIONS_CONNECTION_ERROR_H
 
--- a/azure_uamqp_c/amqp_definitions_data.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_data.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_DATA_H
 #define AMQP_DEFINITIONS_DATA_H
 
--- a/azure_uamqp_c/amqp_definitions_delivery_annotations.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_delivery_annotations.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_DELIVERY_ANNOTATIONS_H
 #define AMQP_DEFINITIONS_DELIVERY_ANNOTATIONS_H
 
--- a/azure_uamqp_c/amqp_definitions_delivery_number.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_delivery_number.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_DELIVERY_NUMBER_H
 #define AMQP_DEFINITIONS_DELIVERY_NUMBER_H
 
--- a/azure_uamqp_c/amqp_definitions_delivery_tag.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_delivery_tag.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_DELIVERY_TAG_H
 #define AMQP_DEFINITIONS_DELIVERY_TAG_H
 
--- a/azure_uamqp_c/amqp_definitions_detach.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_detach.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_DETACH_H
 #define AMQP_DEFINITIONS_DETACH_H
 
--- a/azure_uamqp_c/amqp_definitions_disposition.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_disposition.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_DISPOSITION_H
 #define AMQP_DEFINITIONS_DISPOSITION_H
 
--- a/azure_uamqp_c/amqp_definitions_end.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_end.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_END_H
 #define AMQP_DEFINITIONS_END_H
 
--- a/azure_uamqp_c/amqp_definitions_error.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_error.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_ERROR_H
 #define AMQP_DEFINITIONS_ERROR_H
 
--- a/azure_uamqp_c/amqp_definitions_fields.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_fields.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_FIELDS_H
 #define AMQP_DEFINITIONS_FIELDS_H
 
--- a/azure_uamqp_c/amqp_definitions_filter_set.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_filter_set.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_FILTER_SET_H
 #define AMQP_DEFINITIONS_FILTER_SET_H
 
--- a/azure_uamqp_c/amqp_definitions_flow.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_flow.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_FLOW_H
 #define AMQP_DEFINITIONS_FLOW_H
 
--- a/azure_uamqp_c/amqp_definitions_footer.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_footer.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_FOOTER_H
 #define AMQP_DEFINITIONS_FOOTER_H
 
--- a/azure_uamqp_c/amqp_definitions_handle.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_handle.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_HANDLE_H
 #define AMQP_DEFINITIONS_HANDLE_H
 
--- a/azure_uamqp_c/amqp_definitions_header.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_header.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_HEADER_H
 #define AMQP_DEFINITIONS_HEADER_H
 
--- a/azure_uamqp_c/amqp_definitions_ietf_language_tag.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_ietf_language_tag.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_IETF_LANGUAGE_TAG_H
 #define AMQP_DEFINITIONS_IETF_LANGUAGE_TAG_H
 
--- a/azure_uamqp_c/amqp_definitions_link_error.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_link_error.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_LINK_ERROR_H
 #define AMQP_DEFINITIONS_LINK_ERROR_H
 
--- a/azure_uamqp_c/amqp_definitions_message_annotations.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_message_annotations.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_MESSAGE_ANNOTATIONS_H
 #define AMQP_DEFINITIONS_MESSAGE_ANNOTATIONS_H
 
--- a/azure_uamqp_c/amqp_definitions_message_format.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_message_format.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_MESSAGE_FORMAT_H
 #define AMQP_DEFINITIONS_MESSAGE_FORMAT_H
 
--- a/azure_uamqp_c/amqp_definitions_message_id_binary.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_message_id_binary.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_MESSAGE_ID_BINARY_H
 #define AMQP_DEFINITIONS_MESSAGE_ID_BINARY_H
 
--- a/azure_uamqp_c/amqp_definitions_message_id_string.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_message_id_string.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_MESSAGE_ID_STRING_H
 #define AMQP_DEFINITIONS_MESSAGE_ID_STRING_H
 
--- a/azure_uamqp_c/amqp_definitions_message_id_ulong.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_message_id_ulong.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_MESSAGE_ID_ULONG_H
 #define AMQP_DEFINITIONS_MESSAGE_ID_ULONG_H
 
--- a/azure_uamqp_c/amqp_definitions_message_id_uuid.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_message_id_uuid.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_MESSAGE_ID_UUID_H
 #define AMQP_DEFINITIONS_MESSAGE_ID_UUID_H
 
--- a/azure_uamqp_c/amqp_definitions_milliseconds.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_milliseconds.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_MILLISECONDS_H
 #define AMQP_DEFINITIONS_MILLISECONDS_H
 
--- a/azure_uamqp_c/amqp_definitions_modified.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_modified.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_MODIFIED_H
 #define AMQP_DEFINITIONS_MODIFIED_H
 
--- a/azure_uamqp_c/amqp_definitions_node_properties.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_node_properties.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_NODE_PROPERTIES_H
 #define AMQP_DEFINITIONS_NODE_PROPERTIES_H
 
--- a/azure_uamqp_c/amqp_definitions_open.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_open.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_OPEN_H
 #define AMQP_DEFINITIONS_OPEN_H
 
--- a/azure_uamqp_c/amqp_definitions_properties.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_properties.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_PROPERTIES_H
 #define AMQP_DEFINITIONS_PROPERTIES_H
 
--- a/azure_uamqp_c/amqp_definitions_received.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_received.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_RECEIVED_H
 #define AMQP_DEFINITIONS_RECEIVED_H
 
--- a/azure_uamqp_c/amqp_definitions_receiver_settle_mode.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_receiver_settle_mode.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_RECEIVER_SETTLE_MODE_H
 #define AMQP_DEFINITIONS_RECEIVER_SETTLE_MODE_H
 
--- a/azure_uamqp_c/amqp_definitions_rejected.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_rejected.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_REJECTED_H
 #define AMQP_DEFINITIONS_REJECTED_H
 
--- a/azure_uamqp_c/amqp_definitions_released.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_released.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_RELEASED_H
 #define AMQP_DEFINITIONS_RELEASED_H
 
--- a/azure_uamqp_c/amqp_definitions_role.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_role.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_ROLE_H
 #define AMQP_DEFINITIONS_ROLE_H
 
--- a/azure_uamqp_c/amqp_definitions_sasl_challenge.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_sasl_challenge.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_SASL_CHALLENGE_H
 #define AMQP_DEFINITIONS_SASL_CHALLENGE_H
 
--- a/azure_uamqp_c/amqp_definitions_sasl_code.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_sasl_code.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_SASL_CODE_H
 #define AMQP_DEFINITIONS_SASL_CODE_H
 
--- a/azure_uamqp_c/amqp_definitions_sasl_init.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_sasl_init.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_SASL_INIT_H
 #define AMQP_DEFINITIONS_SASL_INIT_H
 
--- a/azure_uamqp_c/amqp_definitions_sasl_mechanisms.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_sasl_mechanisms.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_SASL_MECHANISMS_H
 #define AMQP_DEFINITIONS_SASL_MECHANISMS_H
 
--- a/azure_uamqp_c/amqp_definitions_sasl_outcome.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_sasl_outcome.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_SASL_OUTCOME_H
 #define AMQP_DEFINITIONS_SASL_OUTCOME_H
 
--- a/azure_uamqp_c/amqp_definitions_sasl_response.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_sasl_response.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_SASL_RESPONSE_H
 #define AMQP_DEFINITIONS_SASL_RESPONSE_H
 
--- a/azure_uamqp_c/amqp_definitions_seconds.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_seconds.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_SECONDS_H
 #define AMQP_DEFINITIONS_SECONDS_H
 
--- a/azure_uamqp_c/amqp_definitions_sender_settle_mode.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_sender_settle_mode.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_SENDER_SETTLE_MODE_H
 #define AMQP_DEFINITIONS_SENDER_SETTLE_MODE_H
 
--- a/azure_uamqp_c/amqp_definitions_sequence_no.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_sequence_no.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_SEQUENCE_NO_H
 #define AMQP_DEFINITIONS_SEQUENCE_NO_H
 
--- a/azure_uamqp_c/amqp_definitions_session_error.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_session_error.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_SESSION_ERROR_H
 #define AMQP_DEFINITIONS_SESSION_ERROR_H
 
--- a/azure_uamqp_c/amqp_definitions_source.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_source.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_SOURCE_H
 #define AMQP_DEFINITIONS_SOURCE_H
 
--- a/azure_uamqp_c/amqp_definitions_target.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_target.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_TARGET_H
 #define AMQP_DEFINITIONS_TARGET_H
 
--- a/azure_uamqp_c/amqp_definitions_terminus_durability.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_terminus_durability.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_TERMINUS_DURABILITY_H
 #define AMQP_DEFINITIONS_TERMINUS_DURABILITY_H
 
--- a/azure_uamqp_c/amqp_definitions_terminus_expiry_policy.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_terminus_expiry_policy.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_TERMINUS_EXPIRY_POLICY_H
 #define AMQP_DEFINITIONS_TERMINUS_EXPIRY_POLICY_H
 
--- a/azure_uamqp_c/amqp_definitions_transfer.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_transfer.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_TRANSFER_H
 #define AMQP_DEFINITIONS_TRANSFER_H
 
--- a/azure_uamqp_c/amqp_definitions_transfer_number.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_definitions_transfer_number.h	Mon Jun 11 15:39:52 2018 -0700
@@ -3,6 +3,9 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+// This file is generated. DO NOT EDIT it manually.
+// The generator that produces it is located at /uamqp_generator/uamqp_generator.sln
+
 #ifndef AMQP_DEFINITIONS_TRANSFER_NUMBER_H
 #define AMQP_DEFINITIONS_TRANSFER_NUMBER_H
 
--- a/azure_uamqp_c/amqp_frame_codec.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqp_frame_codec.h	Mon Jun 11 15:39:52 2018 -0700
@@ -26,7 +26,7 @@
 #define AMQP_END                (uint64_t)0x17
 #define AMQP_CLOSE              (uint64_t)0x18
 
-typedef struct AMQP_FRAME_CODEC_INSTANCE_TAG* AMQP_FRAME_CODEC_HANDLE;
+typedef struct AMQP_FRAME_CODEC_TAG* AMQP_FRAME_CODEC_HANDLE;
 typedef void(*AMQP_EMPTY_FRAME_RECEIVED_CALLBACK)(void* context, uint16_t channel);
 typedef void(*AMQP_FRAME_RECEIVED_CALLBACK)(void* context, uint16_t channel, AMQP_VALUE performative, const unsigned char* payload_bytes, uint32_t frame_payload_size);
 typedef void(*AMQP_FRAME_CODEC_ERROR_CALLBACK)(void* context);
--- a/azure_uamqp_c/amqpvalue.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/amqpvalue.h	Mon Jun 11 15:39:52 2018 -0700
@@ -75,6 +75,11 @@
     MOCKABLE_FUNCTION(, int, amqpvalue_get_map_pair_count, AMQP_VALUE, map, uint32_t*, pair_count);
     MOCKABLE_FUNCTION(, int, amqpvalue_get_map_key_value_pair, AMQP_VALUE, map, uint32_t, index, AMQP_VALUE*, key, AMQP_VALUE*, value);
     MOCKABLE_FUNCTION(, int, amqpvalue_get_map, AMQP_VALUE, from_value, AMQP_VALUE*, map);
+    MOCKABLE_FUNCTION(, AMQP_VALUE, amqpvalue_create_array);
+    MOCKABLE_FUNCTION(, int, amqpvalue_add_array_item, AMQP_VALUE, value, AMQP_VALUE, array_item_value);
+    MOCKABLE_FUNCTION(, AMQP_VALUE, amqpvalue_get_array_item, AMQP_VALUE, value, uint32_t, index);
+    MOCKABLE_FUNCTION(, int, amqpvalue_get_array_item_count, AMQP_VALUE, value, uint32_t*, count);
+    MOCKABLE_FUNCTION(, int, amqpvalue_get_array, AMQP_VALUE, value, AMQP_VALUE*, array_value);
     MOCKABLE_FUNCTION(, AMQP_TYPE, amqpvalue_get_type, AMQP_VALUE, value);
 
     MOCKABLE_FUNCTION(, void, amqpvalue_destroy, AMQP_VALUE, value);
@@ -96,13 +101,7 @@
     MOCKABLE_FUNCTION(, void, amqpvalue_decoder_destroy, AMQPVALUE_DECODER_HANDLE, handle);
     MOCKABLE_FUNCTION(, int, amqpvalue_decode_bytes, AMQPVALUE_DECODER_HANDLE, handle, const unsigned char*, buffer, size_t, size);
 
-    /* misc for now */
-    MOCKABLE_FUNCTION(, AMQP_VALUE, amqpvalue_create_array);
-    MOCKABLE_FUNCTION(, int, amqpvalue_get_array_item_count, AMQP_VALUE, value, uint32_t*, count);
-    MOCKABLE_FUNCTION(, int, amqpvalue_add_array_item, AMQP_VALUE, value, AMQP_VALUE, array_item_value);
-    MOCKABLE_FUNCTION(, AMQP_VALUE, amqpvalue_get_array_item, AMQP_VALUE, value, uint32_t, index);
-    MOCKABLE_FUNCTION(, int, amqpvalue_get_array, AMQP_VALUE, value, AMQP_VALUE*, array_value);
-
+    /* misc for now, not spec'd */
     MOCKABLE_FUNCTION(, AMQP_VALUE, amqpvalue_get_inplace_descriptor, AMQP_VALUE, value);
     MOCKABLE_FUNCTION(, AMQP_VALUE, amqpvalue_get_inplace_described_value, AMQP_VALUE, value);
 
--- a/azure_uamqp_c/connection.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/connection.h	Mon Jun 11 15:39:52 2018 -0700
@@ -12,6 +12,8 @@
 #include "azure_uamqp_c/amqp_frame_codec.h"
 #include "azure_uamqp_c/amqp_definitions_fields.h"
 #include "azure_uamqp_c/amqp_definitions_milliseconds.h"
+#include "azure_uamqp_c/amqp_definitions_error.h"
+#include "azure_uamqp_c/amqpvalue.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -19,57 +21,59 @@
 
     typedef struct CONNECTION_INSTANCE_TAG* CONNECTION_HANDLE;
     typedef struct ENDPOINT_INSTANCE_TAG* ENDPOINT_HANDLE;
+    typedef struct ON_CONNECTION_CLOSED_EVENT_SUBSCRIPTION_TAG* ON_CONNECTION_CLOSED_EVENT_SUBSCRIPTION_HANDLE;
 
     typedef enum CONNECTION_STATE_TAG
     {
-        /* Codes_SRS_CONNECTION_01_039: [START In this state a connection exists, but nothing has been sent or received. This is the state an implementation would be in immediately after performing a socket connect or socket accept.] */
+        /* Codes_S_R_S_CONNECTION_01_039: [START In this state a connection exists, but nothing has been sent or received. This is the state an implementation would be in immediately after performing a socket connect or socket accept.] */
         CONNECTION_STATE_START,
 
-        /* Codes_SRS_CONNECTION_01_040: [HDR RCVD In this state the connection header has been received from the peer but a connection header has not been sent.] */
+        /* Codes_S_R_S_CONNECTION_01_040: [HDR RCVD In this state the connection header has been received from the peer but a connection header has not been sent.] */
         CONNECTION_STATE_HDR_RCVD,
 
-        /* Codes_SRS_CONNECTION_01_041: [HDR SENT In this state the connection header has been sent to the peer but no connection header has been received.] */
+        /* Codes_S_R_S_CONNECTION_01_041: [HDR SENT In this state the connection header has been sent to the peer but no connection header has been received.] */
         CONNECTION_STATE_HDR_SENT,
 
-        /* Codes_SRS_CONNECTION_01_042: [HDR EXCH In this state the connection header has been sent to the peer and a connection header has been received from the peer.] */
+        /* Codes_S_R_S_CONNECTION_01_042: [HDR EXCH In this state the connection header has been sent to the peer and a connection header has been received from the peer.] */
         CONNECTION_STATE_HDR_EXCH,
 
-        /* Codes_SRS_CONNECTION_01_043: [OPEN PIPE In this state both the connection header and the open frame have been sent but nothing has been received.] */
+        /* Codes_S_R_S_CONNECTION_01_043: [OPEN PIPE In this state both the connection header and the open frame have been sent but nothing has been received.] */
         CONNECTION_STATE_OPEN_PIPE,
 
-        /* Codes_SRS_CONNECTION_01_044: [OC PIPE In this state, the connection header, the open frame, any pipelined connection traffic, and the close frame have been sent but nothing has been received.] */
+        /* Codes_S_R_S_CONNECTION_01_044: [OC PIPE In this state, the connection header, the open frame, any pipelined connection traffic, and the close frame have been sent but nothing has been received.] */
         CONNECTION_STATE_OC_PIPE,
 
-        /* Codes_SRS_CONNECTION_01_045: [OPEN RCVD In this state the connection headers have been exchanged. An open frame has been received from the peer but an open frame has not been sent.] */
+        /* Codes_S_R_S_CONNECTION_01_045: [OPEN RCVD In this state the connection headers have been exchanged. An open frame has been received from the peer but an open frame has not been sent.] */
         CONNECTION_STATE_OPEN_RCVD,
 
-        /* Codes_SRS_CONNECTION_01_046: [OPEN SENT In this state the connection headers have been exchanged. An open frame has been sent to the peer but no open frame has yet been received.] */
+        /* Codes_S_R_S_CONNECTION_01_046: [OPEN SENT In this state the connection headers have been exchanged. An open frame has been sent to the peer but no open frame has yet been received.] */
         CONNECTION_STATE_OPEN_SENT,
 
-        /* Codes_SRS_CONNECTION_01_047: [CLOSE PIPE In this state the connection headers have been exchanged. An open frame, any pipelined connection traffic, and the close frame have been sent but no open frame has yet been received from the peer.] */
+        /* Codes_S_R_S_CONNECTION_01_047: [CLOSE PIPE In this state the connection headers have been exchanged. An open frame, any pipelined connection traffic, and the close frame have been sent but no open frame has yet been received from the peer.] */
         CONNECTION_STATE_CLOSE_PIPE,
 
-        /* Codes_SRS_CONNECTION_01_048: [OPENED In this state the connection header and the open frame have been both sent and received.] */
+        /* Codes_S_R_S_CONNECTION_01_048: [OPENED In this state the connection header and the open frame have been both sent and received.] */
         CONNECTION_STATE_OPENED,
 
-        /* Codes_SRS_CONNECTION_01_049: [CLOSE RCVD In this state a close frame has been received indicating that the peer has initiated an AMQP close.] */
+        /* Codes_S_R_S_CONNECTION_01_049: [CLOSE RCVD In this state a close frame has been received indicating that the peer has initiated an AMQP close.] */
         CONNECTION_STATE_CLOSE_RCVD,
 
-        /* Codes_SRS_CONNECTION_01_053: [CLOSE SENT In this state a close frame has been sent to the peer. It is illegal to write anything more onto the connection, however there could potentially still be incoming frames.] */
+        /* Codes_S_R_S_CONNECTION_01_053: [CLOSE SENT In this state a close frame has been sent to the peer. It is illegal to write anything more onto the connection, however there could potentially still be incoming frames.] */
         CONNECTION_STATE_CLOSE_SENT,
 
-        /* Codes_SRS_CONNECTION_01_055: [DISCARDING The DISCARDING state is a variant of the CLOSE SENT state where the close is triggered by an error.] */
+        /* Codes_S_R_S_CONNECTION_01_055: [DISCARDING The DISCARDING state is a variant of the CLOSE SENT state where the close is triggered by an error.] */
         CONNECTION_STATE_DISCARDING,
 
-        /* Codes_SRS_CONNECTION_01_057: [END In this state it is illegal for either endpoint to write anything more onto the connection. The connection can be safely closed and discarded.] */
+        /* Codes_S_R_S_CONNECTION_01_057: [END In this state it is illegal for either endpoint to write anything more onto the connection. The connection can be safely closed and discarded.] */
         CONNECTION_STATE_END,
 
-        /* Codes_SRS_CONNECTION_09_001: [ERROR In this state the connection has failed, most likely due to a socket error, and should not be reused.] */
+        /* Codes_S_R_S_CONNECTION_09_001: [ERROR In this state the connection has failed, most likely due to a socket error, and should not be reused.] */
         CONNECTION_STATE_ERROR
     } CONNECTION_STATE;
 
     typedef void(*ON_ENDPOINT_FRAME_RECEIVED)(void* context, AMQP_VALUE performative, uint32_t frame_payload_size, const unsigned char* payload_bytes);
     typedef void(*ON_CONNECTION_STATE_CHANGED)(void* context, CONNECTION_STATE new_connection_state, CONNECTION_STATE previous_connection_state);
+    typedef void(*ON_CONNECTION_CLOSE_RECEIVED)(void* context, ERROR_HANDLE error);
     typedef bool(*ON_NEW_ENDPOINT)(void* context, ENDPOINT_HANDLE new_endpoint);
 
     MOCKABLE_FUNCTION(, CONNECTION_HANDLE, connection_create, XIO_HANDLE, io, const char*, hostname, const char*, container_id, ON_NEW_ENDPOINT, on_new_endpoint, void*, callback_context);
@@ -77,7 +81,7 @@
     MOCKABLE_FUNCTION(, void, connection_destroy, CONNECTION_HANDLE, connection);
     MOCKABLE_FUNCTION(, int, connection_open, CONNECTION_HANDLE, connection);
     MOCKABLE_FUNCTION(, int, connection_listen, CONNECTION_HANDLE, connection);
-    MOCKABLE_FUNCTION(, int, connection_close, CONNECTION_HANDLE, connection, const char*, condition_value, const char*, description);
+    MOCKABLE_FUNCTION(, int, connection_close, CONNECTION_HANDLE, connection, const char*, condition_value, const char*, description, AMQP_VALUE, info);
     MOCKABLE_FUNCTION(, int, connection_set_max_frame_size, CONNECTION_HANDLE, connection, uint32_t, max_frame_size);
     MOCKABLE_FUNCTION(, int, connection_get_max_frame_size, CONNECTION_HANDLE, connection, uint32_t*, max_frame_size);
     MOCKABLE_FUNCTION(, int, connection_set_channel_max, CONNECTION_HANDLE, connection, uint16_t, channel_max);
@@ -97,6 +101,9 @@
     MOCKABLE_FUNCTION(, int, connection_encode_frame, ENDPOINT_HANDLE, endpoint, AMQP_VALUE, performative, PAYLOAD*, payloads, size_t, payload_count, ON_SEND_COMPLETE, on_send_complete, void*, callback_context);
     MOCKABLE_FUNCTION(, void, connection_set_trace, CONNECTION_HANDLE, connection, bool, trace_on);
 
+    MOCKABLE_FUNCTION(, ON_CONNECTION_CLOSED_EVENT_SUBSCRIPTION_HANDLE, connection_subscribe_on_connection_close_received, CONNECTION_HANDLE, connection, ON_CONNECTION_CLOSE_RECEIVED, on_connection_close_received, void*, context);
+    MOCKABLE_FUNCTION(, void, connection_unsubscribe_on_connection_close_received, ON_CONNECTION_CLOSED_EVENT_SUBSCRIPTION_HANDLE, event_subscription);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
--- a/azure_uamqp_c/header_detect_io.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/header_detect_io.h	Mon Jun 11 15:39:52 2018 -0700
@@ -34,9 +34,9 @@
 		HEADER_DETECT_ENTRY* header_detect_entries;
 		size_t header_detect_entry_count;
 	} HEADER_DETECT_IO_CONFIG;
-    
-	MOCKABLE_FUNCTION(, const AMQP_HEADER, header_detect_io_get_amqp_header);
-	MOCKABLE_FUNCTION(, const AMQP_HEADER, header_detect_io_get_sasl_amqp_header);
+
+	MOCKABLE_FUNCTION(, AMQP_HEADER, header_detect_io_get_amqp_header);
+	MOCKABLE_FUNCTION(, AMQP_HEADER, header_detect_io_get_sasl_amqp_header);
 	MOCKABLE_FUNCTION(, const IO_INTERFACE_DESCRIPTION*, header_detect_io_get_interface_description);
 
 #ifdef __cplusplus
--- a/azure_uamqp_c/link.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/link.h	Mon Jun 11 15:39:52 2018 -0700
@@ -46,10 +46,13 @@
 
 DEFINE_ENUM(LINK_DELIVERY_SETTLE_REASON, LINK_DELIVERY_SETTLE_REASON_VALUES)
 
+typedef struct ON_LINK_DETACH_EVENT_SUBSCRIPTION_TAG* ON_LINK_DETACH_EVENT_SUBSCRIPTION_HANDLE;
+
 typedef void(*ON_DELIVERY_SETTLED)(void* context, delivery_number delivery_no, LINK_DELIVERY_SETTLE_REASON reason, AMQP_VALUE delivery_state);
 typedef AMQP_VALUE(*ON_TRANSFER_RECEIVED)(void* context, TRANSFER_HANDLE transfer, uint32_t payload_size, const unsigned char* payload_bytes);
 typedef void(*ON_LINK_STATE_CHANGED)(void* context, LINK_STATE new_link_state, LINK_STATE previous_link_state);
 typedef void(*ON_LINK_FLOW_ON)(void* context);
+typedef void(*ON_LINK_DETACH_RECEIVED)(void* context, ERROR_HANDLE error);
 
 MOCKABLE_FUNCTION(, LINK_HANDLE, link_create, SESSION_HANDLE, session, const char*, name, role, role, AMQP_VALUE, source, AMQP_VALUE, target);
 MOCKABLE_FUNCTION(, 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);
@@ -69,10 +72,12 @@
 MOCKABLE_FUNCTION(, int, link_get_received_message_id, LINK_HANDLE, link, delivery_number*, message_id);
 MOCKABLE_FUNCTION(, int, link_send_disposition, LINK_HANDLE, link, delivery_number, message_number, AMQP_VALUE, delivery_state);
 MOCKABLE_FUNCTION(, 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);
-MOCKABLE_FUNCTION(, int, link_detach, LINK_HANDLE, link, bool, close);
+MOCKABLE_FUNCTION(, int, link_detach, LINK_HANDLE, link, bool, close, const char*, error_condition, const char*, error_description, AMQP_VALUE, info);
 MOCKABLE_FUNCTION(, ASYNC_OPERATION_HANDLE, link_transfer_async, LINK_HANDLE, handle, message_format, message_format, PAYLOAD*, payloads, size_t, payload_count, ON_DELIVERY_SETTLED, on_delivery_settled, void*, callback_context, LINK_TRANSFER_RESULT*, link_transfer_result,tickcounter_ms_t, timeout);
 MOCKABLE_FUNCTION(, void, link_dowork, LINK_HANDLE, link);
 
+MOCKABLE_FUNCTION(, 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);
+MOCKABLE_FUNCTION(, void, link_unsubscribe_on_link_detach_received, ON_LINK_DETACH_EVENT_SUBSCRIPTION_HANDLE, event_subscription);
 
 #ifdef __cplusplus
 }
--- a/azure_uamqp_c/sasl_frame_codec.h	Fri May 04 13:24:52 2018 -0700
+++ b/azure_uamqp_c/sasl_frame_codec.h	Mon Jun 11 15:39:52 2018 -0700
@@ -16,11 +16,11 @@
 
 #include "azure_c_shared_utility/umock_c_prod.h"
 
-#define SASL_MECHANISMS        (uint64_t)0x40
-#define SASL_INIT            (uint64_t)0x41
-#define SASL_CHALLENGE        (uint64_t)0x42
-#define SASL_RESPONSE        (uint64_t)0x43
-#define SASL_OUTCOME        (uint64_t)0x44
+#define SASL_MECHANISMS         (uint64_t)0x40
+#define SASL_INIT               (uint64_t)0x41
+#define SASL_CHALLENGE          (uint64_t)0x42
+#define SASL_RESPONSE           (uint64_t)0x43
+#define SASL_OUTCOME            (uint64_t)0x44
 
 typedef struct SASL_FRAME_CODEC_INSTANCE_TAG* SASL_FRAME_CODEC_HANDLE;
 typedef void(*ON_SASL_FRAME_RECEIVED)(void* context, AMQP_VALUE sasl_frame_value);
--- a/connection.c	Fri May 04 13:24:52 2018 -0700
+++ b/connection.c	Mon Jun 11 15:39:52 2018 -0700
@@ -18,10 +18,10 @@
 #include "azure_uamqp_c/amqpvalue_to_string.h"
 
 /* Requirements satisfied by the virtue of implementing the ISO:*/
-/* Codes_SRS_CONNECTION_01_088: [Any data appearing beyond the protocol header MUST match the version indicated by the protocol header.] */
-/* Codes_SRS_CONNECTION_01_015: [Implementations SHOULD NOT expect to be able to reuse open TCP sockets after close performatives have been exchanged.] */
+/* Codes_S_R_S_CONNECTION_01_088: [Any data appearing beyond the protocol header MUST match the version indicated by the protocol header.] */
+/* Codes_S_R_S_CONNECTION_01_015: [Implementations SHOULD NOT expect to be able to reuse open TCP sockets after close performatives have been exchanged.] */
 
-/* Codes_SRS_CONNECTION_01_087: [The protocol header consists of the upper case ASCII letters "AMQP" followed by a protocol id of zero, followed by three unsigned bytes representing the major, minor, and revision of the protocol version (currently 1 (MAJOR), 0 (MINOR), 0 (REVISION)). In total this is an 8-octet sequence] */
+/* Codes_S_R_S_CONNECTION_01_087: [The protocol header consists of the upper case ASCII letters "AMQP" followed by a protocol id of zero, followed by three unsigned bytes representing the major, minor, and revision of the protocol version (currently 1 (MAJOR), 0 (MINOR), 0 (REVISION)). In total this is an 8-octet sequence] */
 static const unsigned char amqp_header[] = { 'A', 'M', 'Q', 'P', 0, 1, 0, 0 };
 
 typedef enum RECEIVE_FRAME_STATE_TAG
@@ -30,6 +30,12 @@
     RECEIVE_FRAME_STATE_FRAME_DATA
 } RECEIVE_FRAME_STATE;
 
+typedef struct ON_CONNECTION_CLOSED_EVENT_SUBSCRIPTION_TAG
+{
+    ON_CONNECTION_CLOSE_RECEIVED on_connection_close_received;
+    void* context;
+} ON_CONNECTION_CLOSED_EVENT_SUBSCRIPTION;
+
 typedef struct ENDPOINT_INSTANCE_TAG
 {
     uint16_t incoming_channel;
@@ -65,6 +71,8 @@
     ON_IO_ERROR on_io_error;
     void* on_io_error_callback_context;
 
+    ON_CONNECTION_CLOSED_EVENT_SUBSCRIPTION on_connection_close_received_event_subscription;
+
     /* options */
     uint32_t max_frame_size;
     uint16_t channel_max;
@@ -82,7 +90,7 @@
     unsigned int is_trace_on : 1;
 } CONNECTION_INSTANCE;
 
-/* Codes_SRS_CONNECTION_01_258: [on_connection_state_changed shall be invoked whenever the connection state changes.]*/
+/* Codes_S_R_S_CONNECTION_01_258: [on_connection_state_changed shall be invoked whenever the connection state changes.]*/
 static void connection_set_state(CONNECTION_HANDLE connection, CONNECTION_STATE connection_state)
 {
     uint64_t i;
@@ -90,21 +98,24 @@
     CONNECTION_STATE previous_state = connection->connection_state;
     connection->connection_state = connection_state;
 
-    /* Codes_SRS_CONNECTION_22_001: [If a connection state changed occurs and a callback is registered the callback shall be called.] */
+    /* Codes_S_R_S_CONNECTION_22_001: [If a connection state changed occurs and a callback is registered the callback shall be called.] */
     if (connection->on_connection_state_changed)
     {
         connection->on_connection_state_changed(connection->on_connection_state_changed_callback_context, connection_state, previous_state);
     }
 
-    /* Codes_SRS_CONNECTION_01_260: [Each endpoint's on_connection_state_changed shall be called.] */
+    /* Codes_S_R_S_CONNECTION_01_260: [Each endpoint's on_connection_state_changed shall be called.] */
     for (i = 0; i < connection->endpoint_count; i++)
     {
-        /* Codes_SRS_CONNECTION_01_259: [The callback_context passed in connection_create_endpoint.] */
-        connection->endpoints[i]->on_connection_state_changed(connection->endpoints[i]->callback_context, connection_state, previous_state);
+        /* Codes_S_R_S_CONNECTION_01_259: [The callback_context passed in connection_create_endpoint.] */
+        if (connection->endpoints[i]->on_connection_state_changed != NULL)
+        {
+            connection->endpoints[i]->on_connection_state_changed(connection->endpoints[i]->callback_context, connection_state, previous_state);
+        }
     }
 }
 
-// This callback usage needs to be either verified and commented or integrated into 
+// This callback usage needs to be either verified and commented or integrated into
 // the state machine.
 static void unchecked_on_send_complete(void* context, IO_SEND_RESULT send_result)
 {
@@ -116,20 +127,20 @@
 {
     int result;
 
-    /* Codes_SRS_CONNECTION_01_093: [_ When the client opens a new socket connection to a server, it MUST send a protocol header with the client's preferred protocol version.] */
-    /* Codes_SRS_CONNECTION_01_104: [Sending the protocol header shall be done by using xio_send.] */
+    /* Codes_S_R_S_CONNECTION_01_093: [_ When the client opens a new socket connection to a server, it MUST send a protocol header with the client's preferred protocol version.] */
+    /* Codes_S_R_S_CONNECTION_01_104: [Sending the protocol header shall be done by using xio_send.] */
     if (xio_send(connection->io, amqp_header, sizeof(amqp_header), unchecked_on_send_complete, NULL) != 0)
     {
-        /* Codes_SRS_CONNECTION_01_106: [When sending the protocol header fails, the connection shall be immediately closed.] */
+        /* Codes_S_R_S_CONNECTION_01_106: [When sending the protocol header fails, the connection shall be immediately closed.] */
         if (xio_close(connection->io, NULL, NULL) != 0)
         {
             LogError("xio_close failed");
         }
 
-        /* Codes_SRS_CONNECTION_01_057: [END In this state it is illegal for either endpoint to write anything more onto the connection. The connection can be safely closed and discarded.] */
+        /* Codes_S_R_S_CONNECTION_01_057: [END In this state it is illegal for either endpoint to write anything more onto the connection. The connection can be safely closed and discarded.] */
         connection_set_state(connection, CONNECTION_STATE_END);
 
-        /* Codes_SRS_CONNECTION_01_105: [When xio_send fails, connection_dowork shall return a non-zero value.] */
+        /* Codes_S_R_S_CONNECTION_01_105: [When xio_send fails, connection_dowork shall return a non-zero value.] */
         result = __FAILURE__;
     }
     else
@@ -139,7 +150,7 @@
             LOG(AZ_LOG_TRACE, LOG_LINE, "-> Header (AMQP 0.1.0.0)");
         }
 
-        /* Codes_SRS_CONNECTION_01_041: [HDR SENT In this state the connection header has been sent to the peer but no connection header has been received.] */
+        /* Codes_S_R_S_CONNECTION_01_041: [HDR SENT In this state the connection header has been sent to the peer but no connection header has been received.] */
         connection_set_state(connection, CONNECTION_STATE_HDR_SENT);
         result = 0;
     }
@@ -147,6 +158,7 @@
     return result;
 }
 
+#ifndef NO_LOGGING
 static const char* get_frame_type_as_string(AMQP_VALUE descriptor)
 {
     const char* result;
@@ -194,6 +206,7 @@
 
     return result;
 }
+#endif // NO_LOGGING
 
 static void log_incoming_frame(AMQP_VALUE performative)
 {
@@ -248,7 +261,7 @@
 static void on_bytes_encoded(void* context, const unsigned char* bytes, size_t length, bool encode_complete)
 {
     CONNECTION_HANDLE connection = (CONNECTION_HANDLE)context;
-    if (xio_send(connection->io, bytes, length, 
+    if (xio_send(connection->io, bytes, length,
         (encode_complete && connection->on_send_complete != NULL) ? connection->on_send_complete : unchecked_on_send_complete,
         connection->on_send_complete_callback_context) != 0)
     {
@@ -267,12 +280,12 @@
 {
     int result;
 
-    /* Codes_SRS_CONNECTION_01_151: [The connection max_frame_size setting shall be passed down to the frame_codec when the Open frame is sent.] */
+    /* Codes_S_R_S_CONNECTION_01_151: [The connection max_frame_size setting shall be passed down to the frame_codec when the Open frame is sent.] */
     if (frame_codec_set_max_frame_size(connection->frame_codec, connection->max_frame_size) != 0)
     {
         LogError("Cannot set max frame size");
 
-        /* Codes_SRS_CONNECTION_01_207: [If frame_codec_set_max_frame_size fails the connection shall be closed and the state set to END.] */
+        /* Codes_S_R_S_CONNECTION_01_207: [If frame_codec_set_max_frame_size fails the connection shall be closed and the state set to END.] */
         if (xio_close(connection->io, NULL, NULL) != 0)
         {
             LogError("xio_close failed");
@@ -283,13 +296,13 @@
     }
     else
     {
-        /* Codes_SRS_CONNECTION_01_134: [The container id field shall be filled with the container id specified in connection_create.] */
+        /* Codes_S_R_S_CONNECTION_01_134: [The container id field shall be filled with the container id specified in connection_create.] */
         OPEN_HANDLE open_performative = open_create(connection->container_id);
         if (open_performative == NULL)
         {
             LogError("Cannot create OPEN performative");
-            
-            /* Codes_SRS_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
+
+            /* Codes_S_R_S_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
             if (xio_close(connection->io, NULL, NULL) != 0)
             {
                 LogError("xio_close failed");
@@ -300,12 +313,12 @@
         }
         else
         {
-            /* Codes_SRS_CONNECTION_01_137: [The max_frame_size connection setting shall be set in the open frame by using open_set_max_frame_size.] */
+            /* Codes_S_R_S_CONNECTION_01_137: [The max_frame_size connection setting shall be set in the open frame by using open_set_max_frame_size.] */
             if (open_set_max_frame_size(open_performative, connection->max_frame_size) != 0)
             {
                 LogError("Cannot set max frame size");
 
-                /* Codes_SRS_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
+                /* Codes_S_R_S_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
                 if (xio_close(connection->io, NULL, NULL) != 0)
                 {
                     LogError("xio_close failed");
@@ -314,12 +327,12 @@
                 connection_set_state(connection, CONNECTION_STATE_END);
                 result = __FAILURE__;
             }
-            /* Codes_SRS_CONNECTION_01_139: [The channel_max connection setting shall be set in the open frame by using open_set_channel_max.] */
+            /* Codes_S_R_S_CONNECTION_01_139: [The channel_max connection setting shall be set in the open frame by using open_set_channel_max.] */
             else if (open_set_channel_max(open_performative, connection->channel_max) != 0)
             {
                 LogError("Cannot set max channel");
 
-                /* Codes_SRS_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
+                /* Codes_S_R_S_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
                 if (xio_close(connection->io, NULL, NULL) != 0)
                 {
                     LogError("xio_close failed");
@@ -328,12 +341,12 @@
                 connection_set_state(connection, CONNECTION_STATE_END);
                 result = __FAILURE__;
             }
-            /* Codes_SRS_CONNECTION_01_142: [If no idle_timeout value has been specified, no value shall be stamped in the open frame (no call to open_set_idle_time_out shall be made).] */
+            /* Codes_S_R_S_CONNECTION_01_142: [If no idle_timeout value has been specified, no value shall be stamped in the open frame (no call to open_set_idle_time_out shall be made).] */
             else if ((connection->idle_timeout_specified) &&
-                /* Codes_SRS_CONNECTION_01_141: [If idle_timeout has been specified by a call to connection_set_idle_timeout, then that value shall be stamped in the open frame.] */
+                /* Codes_S_R_S_CONNECTION_01_141: [If idle_timeout has been specified by a call to connection_set_idle_timeout, then that value shall be stamped in the open frame.] */
                 (open_set_idle_time_out(open_performative, connection->idle_timeout) != 0))
             {
-                /* Codes_SRS_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
+                /* Codes_S_R_S_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
                 if (xio_close(connection->io, NULL, NULL) != 0)
                 {
                     LogError("xio_close failed");
@@ -342,14 +355,14 @@
                 connection_set_state(connection, CONNECTION_STATE_END);
                 result = __FAILURE__;
             }
-            /* Codes_SRS_CONNECTION_01_136: [If no hostname value has been specified, no value shall be stamped in the open frame (no call to open_set_hostname shall be made).] */
+            /* Codes_S_R_S_CONNECTION_01_136: [If no hostname value has been specified, no value shall be stamped in the open frame (no call to open_set_hostname shall be made).] */
             else if ((connection->host_name != NULL) &&
-                /* Codes_SRS_CONNECTION_01_135: [If hostname has been specified by a call to connection_set_hostname, then that value shall be stamped in the open frame.] */
+                /* Codes_S_R_S_CONNECTION_01_135: [If hostname has been specified by a call to connection_set_hostname, then that value shall be stamped in the open frame.] */
                 (open_set_hostname(open_performative, connection->host_name) != 0))
             {
                 LogError("Cannot set hostname");
 
-                /* Codes_SRS_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
+                /* Codes_S_R_S_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
                 if (xio_close(connection->io, NULL, NULL) != 0)
                 {
                     LogError("xio_close failed");
@@ -358,14 +371,14 @@
                 connection_set_state(connection, CONNECTION_STATE_END);
                 result = __FAILURE__;
             }
-            /* Codes_SRS_CONNECTION_01_243: [If no properties value has been specified, no value shall be stamped in the open frame (no call to open_set_properties shall be made).] */
+            /* Codes_S_R_S_CONNECTION_01_243: [If no properties value has been specified, no value shall be stamped in the open frame (no call to open_set_properties shall be made).] */
             else if ((connection->properties != NULL) &&
-                /* Codes_SRS_CONNECTION_01_244: [If properties has been specified by a call to connection_set_properties, then that value shall be stamped in the open frame.] */
+                /* Codes_S_R_S_CONNECTION_01_244: [If properties has been specified by a call to connection_set_properties, then that value shall be stamped in the open frame.] */
                 (open_set_properties(open_performative, connection->properties) != 0))
             {
                 LogError("Cannot set properties");
 
-                /* Codes_SRS_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
+                /* Codes_S_R_S_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
                 if (xio_close(connection->io, NULL, NULL) != 0)
                 {
                     LogError("xio_close failed");
@@ -381,7 +394,7 @@
                 {
                     LogError("Cannot create OPEN AMQP value");
 
-                    /* Codes_SRS_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
+                    /* Codes_S_R_S_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
                     if (xio_close(connection->io, NULL, NULL) != 0)
                     {
                         LogError("xio_close failed");
@@ -392,18 +405,18 @@
                 }
                 else
                 {
-                    /* Codes_SRS_CONNECTION_01_002: [Each AMQP connection begins with an exchange of capabilities and limitations, including the maximum frame size.] */
-                    /* Codes_SRS_CONNECTION_01_004: [After establishing or accepting a TCP connection and sending the protocol header, each peer MUST send an open frame before sending any other frames.] */
-                    /* Codes_SRS_CONNECTION_01_005: [The open frame describes the capabilities and limits of that peer.] */
-                    /* Codes_SRS_CONNECTION_01_205: [Sending the AMQP OPEN frame shall be done by calling amqp_frame_codec_begin_encode_frame with channel number 0, the actual performative payload and 0 as payload_size.] */
-                    /* Codes_SRS_CONNECTION_01_006: [The open frame can only be sent on channel 0.] */
+                    /* Codes_S_R_S_CONNECTION_01_002: [Each AMQP connection begins with an exchange of capabilities and limitations, including the maximum frame size.] */
+                    /* Codes_S_R_S_CONNECTION_01_004: [After establishing or accepting a TCP connection and sending the protocol header, each peer MUST send an open frame before sending any other frames.] */
+                    /* Codes_S_R_S_CONNECTION_01_005: [The open frame describes the capabilities and limits of that peer.] */
+                    /* Codes_S_R_S_CONNECTION_01_205: [Sending the AMQP OPEN frame shall be done by calling amqp_frame_codec_begin_encode_frame with channel number 0, the actual performative payload and 0 as payload_size.] */
+                    /* Codes_S_R_S_CONNECTION_01_006: [The open frame can only be sent on channel 0.] */
                     connection->on_send_complete = NULL;
                     connection->on_send_complete_callback_context = NULL;
                     if (amqp_frame_codec_encode_frame(connection->amqp_frame_codec, 0, open_performative_value, NULL, 0, on_bytes_encoded, connection) != 0)
                     {
                         LogError("amqp_frame_codec_encode_frame failed");
 
-                        /* Codes_SRS_CONNECTION_01_206: [If sending the frame fails, the connection shall be closed and state set to END.] */
+                        /* Codes_S_R_S_CONNECTION_01_206: [If sending the frame fails, the connection shall be closed and state set to END.] */
                         if (xio_close(connection->io, NULL, NULL) != 0)
                         {
                             LogError("xio_close failed");
@@ -419,7 +432,7 @@
                             log_outgoing_frame(open_performative_value);
                         }
 
-                        /* Codes_SRS_CONNECTION_01_046: [OPEN SENT In this state the connection headers have been exchanged. An open frame has been sent to the peer but no open frame has yet been received.] */
+                        /* Codes_S_R_S_CONNECTION_01_046: [OPEN SENT In this state the connection headers have been exchanged. An open frame has been sent to the peer but no open frame has yet been received.] */
                         connection_set_state(connection, CONNECTION_STATE_OPEN_SENT);
                         result = 0;
                     }
@@ -440,7 +453,7 @@
     int result;
     CLOSE_HANDLE close_performative;
 
-    /* Codes_SRS_CONNECTION_01_217: [The CLOSE frame shall be constructed by using close_create.] */
+    /* Codes_S_R_S_CONNECTION_01_217: [The CLOSE frame shall be constructed by using close_create.] */
     close_performative = close_create();
     if (close_performative == NULL)
     {
@@ -450,7 +463,7 @@
     else
     {
         if ((error_handle != NULL) &&
-            /* Codes_SRS_CONNECTION_01_238: [If set, this field indicates that the connection is being closed due to an error condition.] */
+            /* Codes_S_R_S_CONNECTION_01_238: [If set, this field indicates that the connection is being closed due to an error condition.] */
             (close_set_error(close_performative, error_handle) != 0))
         {
             LogError("Cannot set error on CLOSE");
@@ -466,8 +479,8 @@
             }
             else
             {
-                /* Codes_SRS_CONNECTION_01_215: [Sending the AMQP CLOSE frame shall be done by calling amqp_frame_codec_begin_encode_frame with channel number 0, the actual performative payload and 0 as payload_size.] */
-                /* Codes_SRS_CONNECTION_01_013: [However, implementations SHOULD send it on channel 0] */
+                /* Codes_S_R_S_CONNECTION_01_215: [Sending the AMQP CLOSE frame shall be done by calling amqp_frame_codec_begin_encode_frame with channel number 0, the actual performative payload and 0 as payload_size.] */
+                /* Codes_S_R_S_CONNECTION_01_013: [However, implementations SHOULD send it on channel 0] */
                 connection->on_send_complete = NULL;
                 connection->on_send_complete_callback_context = NULL;
                 if (amqp_frame_codec_encode_frame(connection->amqp_frame_codec, 0, close_performative_value, NULL, 0, on_bytes_encoded, connection) != 0)
@@ -495,12 +508,13 @@
     return result;
 }
 
-static void close_connection_with_error(CONNECTION_HANDLE connection, const char* condition_value, const char* description)
+static void close_connection_with_error(CONNECTION_HANDLE connection, const char* condition_value, const char* description, AMQP_VALUE info)
 {
     ERROR_HANDLE error_handle = error_create(condition_value);
+
     if (error_handle == NULL)
     {
-        /* Codes_SRS_CONNECTION_01_214: [If the close frame cannot be constructed or sent, the connection shall be closed and set to the END state.] */
+        /* Codes_S_R_S_CONNECTION_01_214: [If the close frame cannot be constructed or sent, the connection shall be closed and set to the END state.] */
         if (xio_close(connection->io, NULL, NULL) != 0)
         {
             LogError("xio_close failed");
@@ -510,12 +524,25 @@
     }
     else
     {
-        /* Codes_SRS_CONNECTION_01_219: [The error description shall be set to an implementation defined string.] */
+        /* Codes_S_R_S_CONNECTION_01_219: [The error description shall be set to an implementation defined string.] */
         if (error_set_description(error_handle, description) != 0)
         {
             LogError("Cannot set error description on CLOSE frame");
 
-            /* Codes_SRS_CONNECTION_01_214: [If the close frame cannot be constructed or sent, the connection shall be closed and set to the END state.] */
+            /* Codes_S_R_S_CONNECTION_01_214: [If the close frame cannot be constructed or sent, the connection shall be closed and set to the END state.] */
+            if (xio_close(connection->io, NULL, NULL) != 0)
+            {
+                LogError("xio_close failed");
+            }
+
+            connection_set_state(connection, CONNECTION_STATE_END);
+        }
+        else if ((info != NULL) &&
+            (error_set_info(error_handle, info) != 0))
+        {
+            LogError("Cannot set error info on CLOSE frame");
+
+            /* Codes_S_R_S_CONNECTION_01_214: [If the close frame cannot be constructed or sent, the connection shall be closed and set to the END state.] */
             if (xio_close(connection->io, NULL, NULL) != 0)
             {
                 LogError("xio_close failed");
@@ -527,7 +554,7 @@
         {
             LogError("Cannot send CLOSE frame");
 
-            /* Codes_SRS_CONNECTION_01_214: [If the close frame cannot be constructed or sent, the connection shall be closed and set to the END state.] */
+            /* Codes_S_R_S_CONNECTION_01_214: [If the close frame cannot be constructed or sent, the connection shall be closed and set to the END state.] */
             if (xio_close(connection->io, NULL, NULL) != 0)
             {
                 LogError("xio_close failed");
@@ -537,9 +564,9 @@
         }
         else
         {
-            /* Codes_SRS_CONNECTION_01_213: [When passing the bytes to frame_codec fails, a CLOSE frame shall be sent and the state shall be set to DISCARDING.] */
-            /* Codes_SRS_CONNECTION_01_055: [DISCARDING The DISCARDING state is a variant of the CLOSE SENT state where the close is triggered by an error.] */
-            /* Codes_SRS_CONNECTION_01_010: [After writing this frame the peer SHOULD continue to read from the connection until it receives the partner's close frame ] */
+            /* Codes_S_R_S_CONNECTION_01_213: [When passing the bytes to frame_codec fails, a CLOSE frame shall be sent and the state shall be set to DISCARDING.] */
+            /* Codes_S_R_S_CONNECTION_01_055: [DISCARDING The DISCARDING state is a variant of the CLOSE SENT state where the close is triggered by an error.] */
+            /* Codes_S_R_S_CONNECTION_01_010: [After writing this frame the peer SHOULD continue to read from the connection until it receives the partner's close frame ] */
             connection_set_state(connection, CONNECTION_STATE_DISCARDING);
         }
 
@@ -610,14 +637,14 @@
         result = __FAILURE__;
         break;
 
-    /* Codes_SRS_CONNECTION_01_039: [START In this state a connection exists, but nothing has been sent or received. This is the state an implementation would be in immediately after performing a socket connect or socket accept.] */
+    /* Codes_S_R_S_CONNECTION_01_039: [START In this state a connection exists, but nothing has been sent or received. This is the state an implementation would be in immediately after performing a socket connect or socket accept.] */
     case CONNECTION_STATE_START:
 
-    /* Codes_SRS_CONNECTION_01_041: [HDR SENT In this state the connection header has been sent to the peer but no connection header has been received.] */
+    /* Codes_S_R_S_CONNECTION_01_041: [HDR SENT In this state the connection header has been sent to the peer but no connection header has been received.] */
     case CONNECTION_STATE_HDR_SENT:
         if (b != amqp_header[connection->header_bytes_received])
         {
-            /* Codes_SRS_CONNECTION_01_089: [If the incoming and outgoing protocol headers do not match, both peers MUST close their outgoing stream] */
+            /* Codes_S_R_S_CONNECTION_01_089: [If the incoming and outgoing protocol headers do not match, both peers MUST close their outgoing stream] */
             if (xio_close(connection->io, NULL, NULL) != 0)
             {
                 LogError("xio_close failed");
@@ -649,28 +676,28 @@
         }
         break;
 
-    /* Codes_SRS_CONNECTION_01_040: [HDR RCVD In this state the connection header has been received from the peer but a connection header has not been sent.] */
+    /* Codes_S_R_S_CONNECTION_01_040: [HDR RCVD In this state the connection header has been received from the peer but a connection header has not been sent.] */
     case CONNECTION_STATE_HDR_RCVD:
 
-    /* Codes_SRS_CONNECTION_01_042: [HDR EXCH In this state the connection header has been sent to the peer and a connection header has been received from the peer.] */
+    /* Codes_S_R_S_CONNECTION_01_042: [HDR EXCH In this state the connection header has been sent to the peer and a connection header has been received from the peer.] */
     /* we should not really get into this state, but just in case, we would treat that in the same way as HDR_RCVD */
     case CONNECTION_STATE_HDR_EXCH:
 
-    /* Codes_SRS_CONNECTION_01_045: [OPEN RCVD In this state the connection headers have been exchanged. An open frame has been received from the peer but an open frame has not been sent.] */
+    /* Codes_S_R_S_CONNECTION_01_045: [OPEN RCVD In this state the connection headers have been exchanged. An open frame has been received from the peer but an open frame has not been sent.] */
     case CONNECTION_STATE_OPEN_RCVD:
 
-    /* Codes_SRS_CONNECTION_01_046: [OPEN SENT In this state the connection headers have been exchanged. An open frame has been sent to the peer but no open frame has yet been received.] */
+    /* Codes_S_R_S_CONNECTION_01_046: [OPEN SENT In this state the connection headers have been exchanged. An open frame has been sent to the peer but no open frame has yet been received.] */
     case CONNECTION_STATE_OPEN_SENT:
 
-    /* Codes_SRS_CONNECTION_01_048: [OPENED In this state the connection header and the open frame have been both sent and received.] */
+    /* Codes_S_R_S_CONNECTION_01_048: [OPENED In this state the connection header and the open frame have been both sent and received.] */
     case CONNECTION_STATE_OPENED:
-        /* Codes_SRS_CONNECTION_01_212: [After the initial handshake has been done all bytes received from the io instance shall be passed to the frame_codec for decoding by calling frame_codec_receive_bytes.] */
+        /* Codes_S_R_S_CONNECTION_01_212: [After the initial handshake has been done all bytes received from the io instance shall be passed to the frame_codec for decoding by calling frame_codec_receive_bytes.] */
         if (frame_codec_receive_bytes(connection->frame_codec, &b, 1) != 0)
         {
             LogError("Cannot process received bytes");
-            /* Codes_SRS_CONNECTION_01_218: [The error amqp:internal-error shall be set in the error.condition field of the CLOSE frame.] */
-            /* Codes_SRS_CONNECTION_01_219: [The error description shall be set to an implementation defined string.] */
-            close_connection_with_error(connection, "amqp:internal-error", "connection_byte_received::frame_codec_receive_bytes failed");
+            /* Codes_S_R_S_CONNECTION_01_218: [The error amqp:internal-error shall be set in the error.condition field of the CLOSE frame.] */
+            /* Codes_S_R_S_CONNECTION_01_219: [The error description shall be set to an implementation defined string.] */
+            close_connection_with_error(connection, "amqp:internal-error", "connection_byte_received::frame_codec_receive_bytes failed", NULL);
             result = __FAILURE__;
         }
         else
@@ -704,7 +731,7 @@
 
     if (io_open_result == IO_OPEN_OK)
     {
-        /* Codes_SRS_CONNECTION_01_084: [The connection_instance state machine implementing the protocol requirements shall be run as part of connection_dowork.] */
+        /* Codes_S_R_S_CONNECTION_01_084: [The connection_instance state machine implementing the protocol requirements shall be run as part of connection_dowork.] */
         switch (connection->connection_state)
         {
         default:
@@ -712,8 +739,8 @@
             break;
 
         case CONNECTION_STATE_START:
-            /* Codes_SRS_CONNECTION_01_086: [Prior to sending any frames on a connection_instance, each peer MUST start by sending a protocol header that indicates the protocol version used on the connection_instance.] */
-            /* Codes_SRS_CONNECTION_01_091: [The AMQP peer which acted in the role of the TCP client (i.e. the peer that actively opened the connection_instance) MUST immediately send its outgoing protocol header on establishment of the TCP connection_instance.] */
+            /* Codes_S_R_S_CONNECTION_01_086: [Prior to sending any frames on a connection_instance, each peer MUST start by sending a protocol header that indicates the protocol version used on the connection_instance.] */
+            /* Codes_S_R_S_CONNECTION_01_091: [The AMQP peer which acted in the role of the TCP client (i.e. the peer that actively opened the connection_instance) MUST immediately send its outgoing protocol header on establishment of the TCP connection_instance.] */
             if (send_header(connection) != 0)
             {
                 LogError("Cannot send header");
@@ -726,9 +753,9 @@
             break;
 
         case CONNECTION_STATE_HDR_EXCH:
-            /* Codes_SRS_CONNECTION_01_002: [Each AMQP connection_instance begins with an exchange of capabilities and limitations, including the maximum frame size.] */
-            /* Codes_SRS_CONNECTION_01_004: [After establishing or accepting a TCP connection_instance and sending the protocol header, each peer MUST send an open frame before sending any other frames.] */
-            /* Codes_SRS_CONNECTION_01_005: [The open frame describes the capabilities and limits of that peer.] */
+            /* Codes_S_R_S_CONNECTION_01_002: [Each AMQP connection_instance begins with an exchange of capabilities and limitations, including the maximum frame size.] */
+            /* Codes_S_R_S_CONNECTION_01_004: [After establishing or accepting a TCP connection_instance and sending the protocol header, each peer MUST send an open frame before sending any other frames.] */
+            /* Codes_S_R_S_CONNECTION_01_005: [The open frame describes the capabilities and limits of that peer.] */
             if (send_open_frame(connection) != 0)
             {
                 LogError("Cannot send OPEN frame");
@@ -750,7 +777,7 @@
 {
     CONNECTION_HANDLE connection = (CONNECTION_HANDLE)context;
 
-    /* Codes_SRS_CONNECTION_22_005: [If the io notifies the connection instance of an IO_STATE_ERROR state and an io error callback is registered, the connection shall call the registered callback.] */
+    /* Codes_S_R_S_CONNECTION_22_005: [If the io notifies the connection instance of an IO_STATE_ERROR state and an io error callback is registered, the connection shall call the registered callback.] */
     if (connection->on_io_error)
     {
         connection->on_io_error(connection->on_io_error_callback_context);
@@ -758,7 +785,7 @@
 
     if (connection->connection_state != CONNECTION_STATE_END)
     {
-        /* Codes_SRS_CONNECTION_01_202: [If the io notifies the connection instance of an IO_STATE_ERROR state the connection shall be closed and the state set to END.] */
+        /* Codes_S_R_S_CONNECTION_01_202: [If the io notifies the connection instance of an IO_STATE_ERROR state the connection shall be closed and the state set to END.] */
         connection_set_state(connection, CONNECTION_STATE_ERROR);
         if (xio_close(connection->io, NULL, NULL) != 0)
         {
@@ -792,7 +819,7 @@
     if (tickcounter_get_current_ms(connection->tick_counter, &connection->last_frame_received_time) != 0)
     {
         LogError("Cannot get tickcounter value");
-        close_connection_with_error(connection, "amqp:internal-error", "cannot get current tick count");
+        close_connection_with_error(connection, "amqp:internal-error", "cannot get current tick count", NULL);
     }
     else
     {
@@ -803,8 +830,8 @@
             default:
                 if (performative == NULL)
                 {
-                    /* Codes_SRS_CONNECTION_01_223: [If the on_endpoint_frame_received is called with a NULL performative then the connection shall be closed with the error condition amqp:internal-error and an implementation defined error description.] */
-                    close_connection_with_error(connection, "amqp:internal-error", "connection_endpoint_frame_received::NULL performative");
+                    /* Codes_S_R_S_CONNECTION_01_223: [If the on_endpoint_frame_received is called with a NULL performative then the connection shall be closed with the error condition amqp:internal-error and an implementation defined error description.] */
+                    close_connection_with_error(connection, "amqp:internal-error", "connection_endpoint_frame_received::NULL performative", NULL);
                     LogError("connection_endpoint_frame_received::NULL performative");
                 }
                 else
@@ -821,16 +848,16 @@
                     {
                         if (channel != 0)
                         {
-                            /* Codes_SRS_CONNECTION_01_006: [The open frame can only be sent on channel 0.] */
-                            /* Codes_SRS_CONNECTION_01_222: [If an Open frame is received in a manner violating the ISO specification, the connection shall be closed with condition amqp:not-allowed and description being an implementation defined string.] */
-                            close_connection_with_error(connection, "amqp:not-allowed", "OPEN frame received on a channel that is not 0");
+                            /* Codes_S_R_S_CONNECTION_01_006: [The open frame can only be sent on channel 0.] */
+                            /* Codes_S_R_S_CONNECTION_01_222: [If an Open frame is received in a manner violating the ISO specification, the connection shall be closed with condition amqp:not-allowed and description being an implementation defined string.] */
+                            close_connection_with_error(connection, "amqp:not-allowed", "OPEN frame received on a channel that is not 0", NULL);
                             LogError("OPEN frame received on a channel that is not 0");
                         }
 
                         if (connection->connection_state == CONNECTION_STATE_OPENED)
                         {
-                            /* Codes_SRS_CONNECTION_01_239: [If an Open frame is received in the Opened state the connection shall be closed with condition amqp:illegal-state and description being an implementation defined string.] */
-                            close_connection_with_error(connection, "amqp:illegal-state", "OPEN frame received in the OPENED state");
+                            /* Codes_S_R_S_CONNECTION_01_239: [If an Open frame is received in the Opened state the connection shall be closed with condition amqp:illegal-state and description being an implementation defined string.] */
+                            close_connection_with_error(connection, "amqp:illegal-state", "OPEN frame received in the OPENED state", NULL);
                             LogError("OPEN frame received in the OPENED state");
                         }
                         else if ((connection->connection_state == CONNECTION_STATE_OPEN_SENT) ||
@@ -839,9 +866,9 @@
                             OPEN_HANDLE open_handle;
                             if (amqpvalue_get_open(performative, &open_handle) != 0)
                             {
-                                /* Codes_SRS_CONNECTION_01_143: [If any of the values in the received open frame are invalid then the connection shall be closed.] */
-                                /* Codes_SRS_CONNECTION_01_220: [The error amqp:invalid-field shall be set in the error.condition field of the CLOSE frame.] */
-                                close_connection_with_error(connection, "amqp:invalid-field", "connection_endpoint_frame_received::failed parsing OPEN frame");
+                                /* Codes_S_R_S_CONNECTION_01_143: [If any of the values in the received open frame are invalid then the connection shall be closed.] */
+                                /* Codes_S_R_S_CONNECTION_01_220: [The error amqp:invalid-field shall be set in the error.condition field of the CLOSE frame.] */
+                                close_connection_with_error(connection, "amqp:invalid-field", "connection_endpoint_frame_received::failed parsing OPEN frame", NULL);
                                 LogError("connection_endpoint_frame_received::failed parsing OPEN frame");
                             }
                             else
@@ -853,12 +880,12 @@
                                 }
 
                                 if ((open_get_max_frame_size(open_handle, &connection->remote_max_frame_size) != 0) ||
-                                    /* Codes_SRS_CONNECTION_01_167: [Both peers MUST accept frames of up to 512 (MIN-MAX-FRAME-SIZE) octets.] */
+                                    /* Codes_S_R_S_CONNECTION_01_167: [Both peers MUST accept frames of up to 512 (MIN-MAX-FRAME-SIZE) octets.] */
                                     (connection->remote_max_frame_size < 512))
                                 {
-                                    /* Codes_SRS_CONNECTION_01_143: [If any of the values in the received open frame are invalid then the connection shall be closed.] */
-                                    /* Codes_SRS_CONNECTION_01_220: [The error amqp:invalid-field shall be set in the error.condition field of the CLOSE frame.] */
-                                    close_connection_with_error(connection, "amqp:invalid-field", "connection_endpoint_frame_received::failed parsing OPEN frame");
+                                    /* Codes_S_R_S_CONNECTION_01_143: [If any of the values in the received open frame are invalid then the connection shall be closed.] */
+                                    /* Codes_S_R_S_CONNECTION_01_220: [The error amqp:invalid-field shall be set in the error.condition field of the CLOSE frame.] */
+                                    close_connection_with_error(connection, "amqp:invalid-field", "connection_endpoint_frame_received::failed parsing OPEN frame", NULL);
                                     LogError("connection_endpoint_frame_received::failed parsing OPEN frame");
                                 }
                                 else
@@ -890,18 +917,17 @@
                     }
                     else if (is_close_type_by_descriptor(descriptor))
                     {
-                        /* Codes_SRS_CONNECTION_01_012: [A close frame MAY be received on any channel up to the maximum channel number negotiated in open.] */
-                        /* Codes_SRS_CONNECTION_01_242: [The connection module shall accept CLOSE frames even if they have extra payload bytes besides the Close performative.] */
+                        /* Codes_S_R_S_CONNECTION_01_242: [The connection module shall accept CLOSE frames even if they have extra payload bytes besides the Close performative.] */
 
-                        /* Codes_SRS_CONNECTION_01_225: [HDR_RCVD HDR OPEN] */
+                        /* Codes_S_R_S_CONNECTION_01_225: [HDR_RCVD HDR OPEN] */
                         if ((connection->connection_state == CONNECTION_STATE_HDR_RCVD) ||
-                            /* Codes_SRS_CONNECTION_01_227: [HDR_EXCH OPEN OPEN] */
+                            /* Codes_S_R_S_CONNECTION_01_227: [HDR_EXCH OPEN OPEN] */
                             (connection->connection_state == CONNECTION_STATE_HDR_EXCH) ||
-                            /* Codes_SRS_CONNECTION_01_228: [OPEN_RCVD OPEN *] */
+                            /* Codes_S_R_S_CONNECTION_01_228: [OPEN_RCVD OPEN *] */
                             (connection->connection_state == CONNECTION_STATE_OPEN_RCVD) ||
-                            /* Codes_SRS_CONNECTION_01_235: [CLOSE_SENT - * TCP Close for Write] */
+                            /* Codes_S_R_S_CONNECTION_01_235: [CLOSE_SENT - * TCP Close for Write] */
                             (connection->connection_state == CONNECTION_STATE_CLOSE_SENT) ||
-                            /* Codes_SRS_CONNECTION_01_236: [DISCARDING - * TCP Close for Write] */
+                            /* Codes_S_R_S_CONNECTION_01_236: [DISCARDING - * TCP Close for Write] */
                             (connection->connection_state == CONNECTION_STATE_DISCARDING))
                         {
                             if (xio_close(connection->io, NULL, NULL) != 0)
@@ -913,21 +939,28 @@
                         {
                             CLOSE_HANDLE close_handle;
 
-                            /* Codes_SRS_CONNECTION_01_012: [A close frame MAY be received on any channel up to the maximum channel number negotiated in open.] */
+                            /* Codes_S_R_S_CONNECTION_01_012: [A close frame MAY be received on any channel up to the maximum channel number negotiated in open.] */
                             if (channel > connection->channel_max)
                             {
-                                close_connection_with_error(connection, "amqp:invalid-field", "connection_endpoint_frame_received::failed parsing CLOSE frame");
+                                close_connection_with_error(connection, "amqp:invalid-field", "connection_endpoint_frame_received::failed parsing CLOSE frame", NULL);
                                 LogError("connection_endpoint_frame_received::failed parsing CLOSE frame");
                             }
                             else
                             {
                                 if (amqpvalue_get_close(performative, &close_handle) != 0)
                                 {
-                                    close_connection_with_error(connection, "amqp:invalid-field", "connection_endpoint_frame_received::failed parsing CLOSE frame");
+                                    close_connection_with_error(connection, "amqp:invalid-field", "connection_endpoint_frame_received::failed parsing CLOSE frame", NULL);
                                     LogError("connection_endpoint_frame_received::failed parsing CLOSE frame");
                                 }
                                 else
                                 {
+                                    ERROR_HANDLE error;
+
+                                    if (close_get_error(close_handle, &error) != 0)
+                                    {
+                                        error = NULL;
+                                    }
+
                                     close_destroy(close_handle);
 
                                     connection_set_state(connection, CONNECTION_STATE_CLOSE_RCVD);
@@ -937,13 +970,20 @@
                                         LogError("Cannot send CLOSE frame");
                                     }
 
-                                    /* Codes_SRS_CONNECTION_01_214: [If the close frame cannot be constructed or sent, the connection shall be closed and set to the END state.] */
+                                    /* Codes_S_R_S_CONNECTION_01_214: [If the close frame cannot be constructed or sent, the connection shall be closed and set to the END state.] */
                                     if (xio_close(connection->io, NULL, NULL) != 0)
                                     {
                                         LogError("xio_close failed");
                                     }
 
                                     connection_set_state(connection, CONNECTION_STATE_END);
+
+                                    if (connection->on_connection_close_received_event_subscription.on_connection_close_received != NULL)
+                                    {
+                                        connection->on_connection_close_received_event_subscription.on_connection_close_received(connection->on_connection_close_received_event_subscription.context, error);
+                                    }
+
+                                    error_destroy(error);
                                 }
                             }
                         }
@@ -1039,17 +1079,17 @@
                 break;
 
             case CONNECTION_STATE_START:
-                /* Codes_SRS_CONNECTION_01_224: [START HDR HDR] */
+                /* Codes_S_R_S_CONNECTION_01_224: [START HDR HDR] */
             case CONNECTION_STATE_HDR_SENT:
-                /* Codes_SRS_CONNECTION_01_226: [HDR_SENT OPEN HDR] */
+                /* Codes_S_R_S_CONNECTION_01_226: [HDR_SENT OPEN HDR] */
             case CONNECTION_STATE_OPEN_PIPE:
-                /* Codes_SRS_CONNECTION_01_230: [OPEN_PIPE ** HDR] */
+                /* Codes_S_R_S_CONNECTION_01_230: [OPEN_PIPE ** HDR] */
             case CONNECTION_STATE_OC_PIPE:
-                /* Codes_SRS_CONNECTION_01_232: [OC_PIPE - HDR TCP Close for Write] */
+                /* Codes_S_R_S_CONNECTION_01_232: [OC_PIPE - HDR TCP Close for Write] */
             case CONNECTION_STATE_CLOSE_RCVD:
-                /* Codes_SRS_CONNECTION_01_234: [CLOSE_RCVD * - TCP Close for Read] */
+                /* Codes_S_R_S_CONNECTION_01_234: [CLOSE_RCVD * - TCP Close for Read] */
             case CONNECTION_STATE_END:
-                /* Codes_SRS_CONNECTION_01_237: [END - - TCP Close] */
+                /* Codes_S_R_S_CONNECTION_01_237: [END - - TCP Close] */
                 if (xio_close(connection->io, NULL, NULL) != 0)
                 {
                     LogError("xio_close failed");
@@ -1062,7 +1102,7 @@
 
 static void frame_codec_error(void* context)
 {
-    /* Bug: some error handling should happen here 
+    /* Bug: some error handling should happen here
     Filed: uAMQP: frame_codec error and amqp_frame_codec_error should handle the errors */
     LogError("A frame_codec_error occured");
     (void)context;
@@ -1076,14 +1116,14 @@
     (void)context;
 }
 
-/* Codes_SRS_CONNECTION_01_001: [connection_create shall open a new connection to a specified host/port.] */
+/* Codes_S_R_S_CONNECTION_01_001: [connection_create shall open a new connection to a specified host/port.] */
 CONNECTION_HANDLE connection_create(XIO_HANDLE xio, const char* hostname, const char* container_id, ON_NEW_ENDPOINT on_new_endpoint, void* callback_context)
 {
     return connection_create2(xio, hostname, container_id, on_new_endpoint, callback_context, NULL, NULL, NULL, NULL);
 }
 
-/* Codes_SRS_CONNECTION_01_001: [connection_create shall open a new connection to a specified host/port.] */
-/* Codes_SRS_CONNECTION_22_002: [connection_create shall allow registering connections state and io error callbacks.] */
+/* Codes_S_R_S_CONNECTION_01_001: [connection_create shall open a new connection to a specified host/port.] */
+/* Codes_S_R_S_CONNECTION_22_002: [connection_create shall allow registering connections state and io error callbacks.] */
 CONNECTION_HANDLE connection_create2(XIO_HANDLE xio, const char* hostname, const char* container_id, ON_NEW_ENDPOINT on_new_endpoint, void* callback_context, ON_CONNECTION_STATE_CHANGED on_connection_state_changed, void* on_connection_state_changed_context, ON_IO_ERROR on_io_error, void* on_io_error_context)
 {
     CONNECTION_HANDLE connection;
@@ -1091,7 +1131,7 @@
     if ((xio == NULL) ||
         (container_id == NULL))
     {
-        /* Codes_SRS_CONNECTION_01_071: [If xio or container_id is NULL, connection_create shall return NULL.] */
+        /* Codes_S_R_S_CONNECTION_01_071: [If xio or container_id is NULL, connection_create shall return NULL.] */
         LogError("Bad arguments: xio = %p, container_id = %p",
             xio, container_id);
         connection = NULL;
@@ -1099,7 +1139,7 @@
     else
     {
         connection = (CONNECTION_HANDLE)malloc(sizeof(CONNECTION_INSTANCE));
-        /* Codes_SRS_CONNECTION_01_081: [If allocating the memory for the connection fails then connection_create shall return NULL.] */
+        /* Codes_S_R_S_CONNECTION_01_081: [If allocating the memory for the connection fails then connection_create shall return NULL.] */
         if (connection == NULL)
         {
             LogError("Cannot allocate memory for connection");
@@ -1108,11 +1148,11 @@
         {
             connection->io = xio;
 
-            /* Codes_SRS_CONNECTION_01_082: [connection_create shall allocate a new frame_codec instance to be used for frame encoding/decoding.] */
+            /* Codes_S_R_S_CONNECTION_01_082: [connection_create shall allocate a new frame_codec instance to be used for frame encoding/decoding.] */
             connection->frame_codec = frame_codec_create(frame_codec_error, connection);
             if (connection->frame_codec == NULL)
             {
-                /* Codes_SRS_CONNECTION_01_083: [If frame_codec_create fails then connection_create shall return NULL.] */
+                /* Codes_S_R_S_CONNECTION_01_083: [If frame_codec_create fails then connection_create shall return NULL.] */
                 LogError("Cannot create frame_codec");
                 free(connection);
                 connection = NULL;
@@ -1122,7 +1162,7 @@
                 connection->amqp_frame_codec = amqp_frame_codec_create(connection->frame_codec, on_amqp_frame_received, on_empty_amqp_frame_received, amqp_frame_codec_error, connection);
                 if (connection->amqp_frame_codec == NULL)
                 {
-                    /* Codes_SRS_CONNECTION_01_108: [If amqp_frame_codec_create fails, connection_create shall return NULL.] */
+                    /* Codes_S_R_S_CONNECTION_01_108: [If amqp_frame_codec_create fails, connection_create shall return NULL.] */
                     LogError("Cannot create amqp_frame_codec");
                     frame_codec_destroy(connection->frame_codec);
                     free(connection);
@@ -1136,7 +1176,7 @@
                         connection->host_name = (char*)malloc(hostname_length + 1);
                         if (connection->host_name == NULL)
                         {
-                            /* Codes_SRS_CONNECTION_01_081: [If allocating the memory for the connection fails then connection_create shall return NULL.] */
+                            /* Codes_S_R_S_CONNECTION_01_081: [If allocating the memory for the connection fails then connection_create shall return NULL.] */
                             LogError("Cannot allocate memory for host name");
                             amqp_frame_codec_destroy(connection->amqp_frame_codec);
                             frame_codec_destroy(connection->frame_codec);
@@ -1159,7 +1199,7 @@
                         connection->container_id = (char*)malloc(container_id_length + 1);
                         if (connection->container_id == NULL)
                         {
-                            /* Codes_SRS_CONNECTION_01_081: [If allocating the memory for the connection fails then connection_create shall return NULL.] */
+                            /* Codes_S_R_S_CONNECTION_01_081: [If allocating the memory for the connection fails then connection_create shall return NULL.] */
                             LogError("Cannot allocate memory for container_id");
                             free(connection->host_name);
                             amqp_frame_codec_destroy(connection->amqp_frame_codec);
@@ -1184,13 +1224,13 @@
                             {
                                 (void)memcpy(connection->container_id, container_id, container_id_length + 1);
 
-                                /* Codes_SRS_CONNECTION_01_173: [<field name="max-frame-size" type="uint" default="4294967295"/>] */
+                                /* Codes_S_R_S_CONNECTION_01_173: [<field name="max-frame-size" type="uint" default="4294967295"/>] */
                                 connection->max_frame_size = 4294967295u;
                                 /* Codes: [<field name="channel-max" type="ushort" default="65535"/>] */
                                 connection->channel_max = 65535;
 
-                                /* Codes_SRS_CONNECTION_01_175: [<field name="idle-time-out" type="milliseconds"/>] */
-                                /* Codes_SRS_CONNECTION_01_192: [A value of zero is the same as if it was not set (null).] */
+                                /* Codes_S_R_S_CONNECTION_01_175: [<field name="idle-time-out" type="milliseconds"/>] */
+                                /* Codes_S_R_S_CONNECTION_01_192: [A value of zero is the same as if it was not set (null).] */
                                 connection->idle_timeout = 0;
                                 connection->remote_idle_timeout = 0;
                                 connection->remote_idle_timeout_send_frame_millisecond = 0;
@@ -1212,6 +1252,9 @@
                                 connection->on_new_endpoint = on_new_endpoint;
                                 connection->on_new_endpoint_callback_context = callback_context;
 
+                                connection->on_connection_close_received_event_subscription.on_connection_close_received = NULL;
+                                connection->on_connection_close_received_event_subscription.context = NULL;
+
                                 connection->on_io_error = on_io_error;
                                 connection->on_io_error_callback_context = on_io_error_context;
                                 connection->on_connection_state_changed = on_connection_state_changed;
@@ -1232,7 +1275,7 @@
                                 {
                                     connection->last_frame_sent_time = connection->last_frame_received_time;
 
-                                    /* Codes_SRS_CONNECTION_01_072: [When connection_create succeeds, the state of the connection shall be CONNECTION_STATE_START.] */
+                                    /* Codes_S_R_S_CONNECTION_01_072: [When connection_create succeeds, the state of the connection shall be CONNECTION_STATE_START.] */
                                     connection_set_state(connection, CONNECTION_STATE_START);
                                 }
                             }
@@ -1248,17 +1291,17 @@
 
 void connection_destroy(CONNECTION_HANDLE connection)
 {
-    /* Codes_SRS_CONNECTION_01_079: [If handle is NULL, connection_destroy shall do nothing.] */
+    /* Codes_S_R_S_CONNECTION_01_079: [If handle is NULL, connection_destroy shall do nothing.] */
     if (connection == NULL)
     {
         LogError("NULL connection");
     }
     else
     {
-        /* Codes_SRS_CONNECTION_01_073: [connection_destroy shall free all resources associated with a connection.] */
+        /* Codes_S_R_S_CONNECTION_01_073: [connection_destroy shall free all resources associated with a connection.] */
         if (connection->is_underlying_io_open)
         {
-            (void)connection_close(connection, NULL, NULL);
+            (void)connection_close(connection, NULL, NULL, NULL);
         }
 
         amqp_frame_codec_destroy(connection->amqp_frame_codec);
@@ -1272,7 +1315,7 @@
         free(connection->host_name);
         free(connection->container_id);
 
-        /* Codes_SRS_CONNECTION_01_074: [connection_destroy shall close the socket connection.] */
+        /* Codes_S_R_S_CONNECTION_01_074: [connection_destroy shall close the socket connection.] */
         free(connection);
     }
 }
@@ -1351,7 +1394,7 @@
     return result;
 }
 
-int connection_close(CONNECTION_HANDLE connection, const char* condition_value, const char* description)
+int connection_close(CONNECTION_HANDLE connection, const char* condition_value, const char* description, AMQP_VALUE info)
 {
     int result;
 
@@ -1360,11 +1403,18 @@
         LogError("NULL connection");
         result = __FAILURE__;
     }
+    else if ((info != NULL) &&
+        (amqpvalue_get_type(info) != AMQP_TYPE_MAP) &&
+        (amqpvalue_get_type(info) != AMQP_TYPE_NULL))
+    {
+        LogError("Invalid info, expected a map");
+        result = __FAILURE__;
+    }
     else
     {
         if (condition_value != NULL)
         {
-            close_connection_with_error(connection, condition_value, description);
+            close_connection_with_error(connection, condition_value, description, info);
         }
         else
         {
@@ -1393,14 +1443,14 @@
 {
     int result;
 
-    /* Codes_SRS_CONNECTION_01_163: [If connection is NULL, connection_set_max_frame_size shall fail and return a non-zero value.] */
+    /* Codes_S_R_S_CONNECTION_01_163: [If connection is NULL, connection_set_max_frame_size shall fail and return a non-zero value.] */
     if (connection == NULL)
     {
         LogError("NULL connection");
         result = __FAILURE__;
     }
-    /* Codes_SRS_CONNECTION_01_150: [If the max_frame_size is invalid then connection_set_max_frame_size shall fail and return a non-zero value.] */
-    /* Codes_SRS_CONNECTION_01_167: [Both peers MUST accept frames of up to 512 (MIN-MAX-FRAME-SIZE) octets.] */
+    /* Codes_S_R_S_CONNECTION_01_150: [If the max_frame_size is invalid then connection_set_max_frame_size shall fail and return a non-zero value.] */
+    /* Codes_S_R_S_CONNECTION_01_167: [Both peers MUST accept frames of up to 512 (MIN-MAX-FRAME-SIZE) octets.] */
     else if (max_frame_size < 512)
     {
         LogError("max_frame_size too small");
@@ -1408,7 +1458,7 @@
     }
     else
     {
-        /* Codes_SRS_CONNECTION_01_157: [If connection_set_max_frame_size is called after the initial Open frame has been sent, it shall fail and return a non-zero value.] */
+        /* Codes_S_R_S_CONNECTION_01_157: [If connection_set_max_frame_size is called after the initial Open frame has been sent, it shall fail and return a non-zero value.] */
         if (connection->connection_state != CONNECTION_STATE_START)
         {
             LogError("Connection already open");
@@ -1416,11 +1466,11 @@
         }
         else
         {
-            /* Codes_SRS_CONNECTION_01_148: [connection_set_max_frame_size shall set the max_frame_size associated with a connection.] */
-            /* Codes_SRS_CONNECTION_01_164: [If connection_set_max_frame_size fails, the previous max_frame_size setting shall be retained.] */
+            /* Codes_S_R_S_CONNECTION_01_148: [connection_set_max_frame_size shall set the max_frame_size associated with a connection.] */
+            /* Codes_S_R_S_CONNECTION_01_164: [If connection_set_max_frame_size fails, the previous max_frame_size setting shall be retained.] */
             connection->max_frame_size = max_frame_size;
 
-            /* Codes_SRS_CONNECTION_01_149: [On success connection_set_max_frame_size shall return 0.] */
+            /* Codes_S_R_S_CONNECTION_01_149: [On success connection_set_max_frame_size shall return 0.] */
             result = 0;
         }
     }
@@ -1432,7 +1482,7 @@
 {
     int result;
 
-    /* Codes_SRS_CONNECTION_01_170: [If connection or max_frame_size is NULL, connection_get_max_frame_size shall fail and return a non-zero value.] */
+    /* Codes_S_R_S_CONNECTION_01_170: [If connection or max_frame_size is NULL, connection_get_max_frame_size shall fail and return a non-zero value.] */
     if ((connection == NULL) ||
         (max_frame_size == NULL))
     {
@@ -1442,10 +1492,10 @@
     }
     else
     {
-        /* Codes_SRS_CONNECTION_01_168: [connection_get_max_frame_size shall return in the max_frame_size argument the current max frame size setting.] */
+        /* Codes_S_R_S_CONNECTION_01_168: [connection_get_max_frame_size shall return in the max_frame_size argument the current max frame size setting.] */
         *max_frame_size = connection->max_frame_size;
 
-        /* Codes_SRS_CONNECTION_01_169: [On success, connection_get_max_frame_size shall return 0.] */
+        /* Codes_S_R_S_CONNECTION_01_169: [On success, connection_get_max_frame_size shall return 0.] */
         result = 0;
     }
 
@@ -1456,7 +1506,7 @@
 {
     int result;
 
-    /* Codes_SRS_CONNECTION_01_181: [If connection is NULL then connection_set_channel_max shall fail and return a non-zero value.] */
+    /* Codes_S_R_S_CONNECTION_01_181: [If connection is NULL then connection_set_channel_max shall fail and return a non-zero value.] */
     if (connection == NULL)
     {
         LogError("NULL connection");
@@ -1464,7 +1514,7 @@
     }
     else
     {
-        /* Codes_SRS_CONNECTION_01_156: [If connection_set_channel_max is called after the initial Open frame has been sent, it shall fail and return a non-zero value.] */
+        /* Codes_S_R_S_CONNECTION_01_156: [If connection_set_channel_max is called after the initial Open frame has been sent, it shall fail and return a non-zero value.] */
         if (connection->connection_state != CONNECTION_STATE_START)
         {
             LogError("Connection already open");
@@ -1472,11 +1522,11 @@
         }
         else
         {
-            /* Codes_SRS_CONNECTION_01_153: [connection_set_channel_max shall set the channel_max associated with a connection.] */
-            /* Codes_SRS_CONNECTION_01_165: [If connection_set_channel_max fails, the previous channel_max setting shall be retained.] */
+            /* Codes_S_R_S_CONNECTION_01_153: [connection_set_channel_max shall set the channel_max associated with a connection.] */
+            /* Codes_S_R_S_CONNECTION_01_165: [If connection_set_channel_max fails, the previous channel_max setting shall be retained.] */
             connection->channel_max = channel_max;
 
-            /* Codes_SRS_CONNECTION_01_154: [On success connection_set_channel_max shall return 0.] */
+            /* Codes_S_R_S_CONNECTION_01_154: [On success connection_set_channel_max shall return 0.] */
             result = 0;
         }
     }
@@ -1488,7 +1538,7 @@
 {
     int result;
 
-    /* Codes_SRS_CONNECTION_01_184: [If connection or channel_max is NULL, connection_get_channel_max shall fail and return a non-zero value.] */
+    /* Codes_S_R_S_CONNECTION_01_184: [If connection or channel_max is NULL, connection_get_channel_max shall fail and return a non-zero value.] */
     if ((connection == NULL) ||
         (channel_max == NULL))
     {
@@ -1498,10 +1548,10 @@
     }
     else
     {
-        /* Codes_SRS_CONNECTION_01_182: [connection_get_channel_max shall return in the channel_max argument the current channel_max setting.] */
+        /* Codes_S_R_S_CONNECTION_01_182: [connection_get_channel_max shall return in the channel_max argument the current channel_max setting.] */
         *channel_max = connection->channel_max;
 
-        /* Codes_SRS_CONNECTION_01_183: [On success, connection_get_channel_max shall return 0.] */
+        /* Codes_S_R_S_CONNECTION_01_183: [On success, connection_get_channel_max shall return 0.] */
         result = 0;
     }
 
@@ -1512,7 +1562,7 @@
 {
     int result;
 
-    /* Codes_SRS_CONNECTION_01_191: [If connection is NULL, connection_set_idle_timeout shall fail and return a non-zero value.] */
+    /* Codes_S_R_S_CONNECTION_01_191: [If connection is NULL, connection_set_idle_timeout shall fail and return a non-zero value.] */
     if (connection == NULL)
     {
         LogError("NULL connection");
@@ -1520,7 +1570,7 @@
     }
     else
     {
-        /* Codes_SRS_CONNECTION_01_158: [If connection_set_idle_timeout is called after the initial Open frame has been sent, it shall fail and return a non-zero value.] */
+        /* Codes_S_R_S_CONNECTION_01_158: [If connection_set_idle_timeout is called after the initial Open frame has been sent, it shall fail and return a non-zero value.] */
         if (connection->connection_state != CONNECTION_STATE_START)
         {
             LogError("Connection already open");
@@ -1528,12 +1578,12 @@
         }
         else
         {
-            /* Codes_SRS_CONNECTION_01_159: [connection_set_idle_timeout shall set the idle_timeout associated with a connection.] */
-            /* Codes_SRS_CONNECTION_01_166: [If connection_set_idle_timeout fails, the previous idle_timeout setting shall be retained.] */
+            /* Codes_S_R_S_CONNECTION_01_159: [connection_set_idle_timeout shall set the idle_timeout associated with a connection.] */
+            /* Codes_S_R_S_CONNECTION_01_166: [If connection_set_idle_timeout fails, the previous idle_timeout setting shall be retained.] */
             connection->idle_timeout = idle_timeout;
             connection->idle_timeout_specified = true;
 
-            /* Codes_SRS_CONNECTION_01_160: [On success connection_set_idle_timeout shall return 0.] */
+            /* Codes_S_R_S_CONNECTION_01_160: [On success connection_set_idle_timeout shall return 0.] */
             result = 0;
         }
     }
@@ -1545,7 +1595,7 @@
 {
     int result;
 
-    /* Codes_SRS_CONNECTION_01_190: [If connection or idle_timeout is NULL, connection_get_idle_timeout shall fail and return a non-zero value.] */
+    /* Codes_S_R_S_CONNECTION_01_190: [If connection or idle_timeout is NULL, connection_get_idle_timeout shall fail and return a non-zero value.] */
     if ((connection == NULL) ||
         (idle_timeout == NULL))
     {
@@ -1555,10 +1605,10 @@
     }
     else
     {
-        /* Codes_SRS_CONNECTION_01_188: [connection_get_idle_timeout shall return in the idle_timeout argument the current idle_timeout setting.] */
+        /* Codes_S_R_S_CONNECTION_01_188: [connection_get_idle_timeout shall return in the idle_timeout argument the current idle_timeout setting.] */
         *idle_timeout = connection->idle_timeout;
 
-        /* Codes_SRS_CONNECTION_01_189: [On success, connection_get_idle_timeout shall return 0.] */
+        /* Codes_S_R_S_CONNECTION_01_189: [On success, connection_get_idle_timeout shall return 0.] */
         result = 0;
     }
 
@@ -1569,7 +1619,7 @@
 {
     int result;
 
-    /* Codes_SRS_CONNECTION_01_261: [If connection is NULL, connection_set_properties shall fail and return a non-zero value.] */
+    /* Codes_S_R_S_CONNECTION_01_261: [If connection is NULL, connection_set_properties shall fail and return a non-zero value.] */
     if (connection == NULL)
     {
         LogError("NULL connection");
@@ -1577,7 +1627,7 @@
     }
     else
     {
-        /* Codes_SRS_CONNECTION_01_262: [If connection_set_properties is called after the initial Open frame has been sent, it shall fail and return a non-zero value.] */
+        /* Codes_S_R_S_CONNECTION_01_262: [If connection_set_properties is called after the initial Open frame has been sent, it shall fail and return a non-zero value.] */
         if (connection->connection_state != CONNECTION_STATE_START)
         {
             LogError("Connection already open");
@@ -1587,32 +1637,32 @@
         {
             if (properties == NULL)
             {
-                /* Codes_SRS_CONNECTION_01_263: [ If `properties` is NULL, the previously stored properties associated with `connection` shall be freed. ]*/
+                /* Codes_S_R_S_CONNECTION_01_263: [ If `properties` is NULL, the previously stored properties associated with `connection` shall be freed. ]*/
                 if (connection->properties != NULL)
                 {
                     fields_destroy(connection->properties);
                     connection->properties = NULL;
                 }
 
-                /* Codes_SRS_CONNECTION_01_264: [ On success it shall return 0. ]*/
+                /* Codes_S_R_S_CONNECTION_01_264: [ On success it shall return 0. ]*/
                 result = 0;
             }
             else
             {
                 fields new_properties;
 
-                /* Codes_SRS_CONNECTION_01_265: [ `connection_set_properties` shall copy the contents of `properties` as the properties contents for the connection instance identified by `connection`. ]*/
-                /* Codes_SRS_CONNECTION_01_266: [ Cloning the properties shall be done by calling `fields_clone`. ]*/
+                /* Codes_S_R_S_CONNECTION_01_265: [ `connection_set_properties` shall copy the contents of `properties` as the properties contents for the connection instance identified by `connection`. ]*/
+                /* Codes_S_R_S_CONNECTION_01_266: [ Cloning the properties shall be done by calling `fields_clone`. ]*/
                 new_properties = fields_clone(properties);
                 if (new_properties == NULL)
                 {
-                    /* Codes_SRS_CONNECTION_01_267: [ If `fields_clone` fails, `connection_set_properties` shall fail and return a non-zero value. ]*/
+                    /* Codes_S_R_S_CONNECTION_01_267: [ If `fields_clone` fails, `connection_set_properties` shall fail and return a non-zero value. ]*/
                     LogError("Cannot clone connection properties");
                     result = __FAILURE__;
                 }
                 else
                 {
-                    /* Codes_SRS_CONNECTION_01_268: [ If setting the properties fails, the previous value shall be preserved. ]*/
+                    /* Codes_S_R_S_CONNECTION_01_268: [ If setting the properties fails, the previous value shall be preserved. ]*/
                     /* Only do the free of the previous value if we could clone the new one*/
                     if (connection->properties != NULL)
                     {
@@ -1621,7 +1671,7 @@
 
                     connection->properties = new_properties;
 
-                    /* Codes_SRS_CONNECTION_01_264: [ On success it shall return 0. ]*/
+                    /* Codes_S_R_S_CONNECTION_01_264: [ On success it shall return 0. ]*/
                     result = 0;
                 }
             }
@@ -1635,7 +1685,7 @@
 {
     int result;
 
-    /* Codes_SRS_CONNECTION_01_269: [If connection or properties is NULL, connection_get_properties shall fail and return a non-zero value.] */
+    /* Codes_S_R_S_CONNECTION_01_269: [If connection or properties is NULL, connection_get_properties shall fail and return a non-zero value.] */
     if ((connection == NULL) ||
         (properties == NULL))
     {
@@ -1647,26 +1697,26 @@
     {
         if (connection->properties == NULL)
         {
-            /* Codes_SRS_CONNECTION_01_270: [ If no properties have been set, `connection_get_properties` shall set `properties` to NULL. ]*/
+            /* Codes_S_R_S_CONNECTION_01_270: [ If no properties have been set, `connection_get_properties` shall set `properties` to NULL. ]*/
             *properties = NULL;
 
-            /* Codes_SRS_CONNECTION_01_271: [On success, connection_get_properties shall return 0.] */
+            /* Codes_S_R_S_CONNECTION_01_271: [On success, connection_get_properties shall return 0.] */
             result = 0;
         }
         else
         {
-            /* Codes_SRS_CONNECTION_01_272: [connection_get_properties shall return in the properties argument the current properties setting.] */
-            /* Codes_SRS_CONNECTION_01_273: [ Cloning the properties shall be done by calling `fields_clone`. ]*/
+            /* Codes_S_R_S_CONNECTION_01_272: [connection_get_properties shall return in the properties argument the current properties setting.] */
+            /* Codes_S_R_S_CONNECTION_01_273: [ Cloning the properties shall be done by calling `fields_clone`. ]*/
             *properties = fields_clone(connection->properties);
             if (*properties == NULL)
             {
-                /* Codes_SRS_CONNECTION_01_274: [ If `fields_clone` fails, `connection_get_properties` shall fail and return a non-zero value. ]*/
+                /* Codes_S_R_S_CONNECTION_01_274: [ If `fields_clone` fails, `connection_get_properties` shall fail and return a non-zero value. ]*/
                 LogError("Cannot clone properties");
                 result = __FAILURE__;
             }
             else
             {
-                /* Codes_SRS_CONNECTION_01_271: [On success, connection_get_properties shall return 0.] */
+                /* Codes_S_R_S_CONNECTION_01_271: [On success, connection_get_properties shall return 0.] */
                 result = 0;
             }
         }
@@ -1712,7 +1762,7 @@
         if (tickcounter_get_current_ms(connection->tick_counter, &current_ms) != 0)
         {
             LogError("Could not get tick counter value");
-            close_connection_with_error(connection, "amqp:internal-error", "Could not get tick count");
+            close_connection_with_error(connection, "amqp:internal-error", "Could not get tick count", NULL);
         }
         else
         {
@@ -1730,7 +1780,7 @@
                     local_deadline = 0;
 
                     /* close connection */
-                    close_connection_with_error(connection, "amqp:internal-error", "No frame received for the idle timeout");
+                    close_connection_with_error(connection, "amqp:internal-error", "No frame received for the idle timeout", NULL);
                 }
             }
 
@@ -1752,7 +1802,7 @@
                     {
                         LogError("Encoding the empty frame failed");
                         /* close connection */
-                        close_connection_with_error(connection, "amqp:internal-error", "Cannot send empty frame");
+                        close_connection_with_error(connection, "amqp:internal-error", "Cannot send empty frame", NULL);
                     }
                     else
                     {
@@ -1776,7 +1826,7 @@
 
 void connection_dowork(CONNECTION_HANDLE connection)
 {
-    /* Codes_SRS_CONNECTION_01_078: [If handle is NULL, connection_dowork shall do nothing.] */
+    /* Codes_S_R_S_CONNECTION_01_078: [If handle is NULL, connection_dowork shall do nothing.] */
     if (connection == NULL)
     {
         LogError("NULL connection");
@@ -1785,7 +1835,7 @@
     {
         if (connection_handle_deadlines(connection) > 0)
         {
-            /* Codes_SRS_CONNECTION_01_076: [connection_dowork shall schedule the underlying IO interface to do its work by calling xio_dowork.] */
+            /* Codes_S_R_S_CONNECTION_01_076: [connection_dowork shall schedule the underlying IO interface to do its work by calling xio_dowork.] */
             xio_dowork(connection->io);
         }
     }
@@ -1795,8 +1845,8 @@
 {
     ENDPOINT_HANDLE result;
 
-    /* Codes_SRS_CONNECTION_01_113: [If connection, on_endpoint_frame_received or on_connection_state_changed is NULL, connection_create_endpoint shall fail and return NULL.] */
-    /* Codes_SRS_CONNECTION_01_193: [The context argument shall be allowed to be NULL.] */
+    /* Codes_S_R_S_CONNECTION_01_113: [If connection, on_endpoint_frame_received or on_connection_state_changed is NULL, connection_create_endpoint shall fail and return NULL.] */
+    /* Codes_S_R_S_CONNECTION_01_193: [The context argument shall be allowed to be NULL.] */
     if (connection == NULL)
     {
         LogError("NULL connection");
@@ -1804,7 +1854,7 @@
     }
     else
     {
-        /* Codes_SRS_CONNECTION_01_115: [If no more endpoints can be created due to all channels being used, connection_create_endpoint shall fail and return NULL.] */
+        /* Codes_S_R_S_CONNECTION_01_115: [If no more endpoints can be created due to all channels being used, connection_create_endpoint shall fail and return NULL.] */
         if (connection->endpoint_count >= connection->channel_max)
         {
             result = NULL;
@@ -1813,7 +1863,7 @@
         {
             uint32_t i = 0;
 
-            /* Codes_SRS_CONNECTION_01_128: [The lowest number outgoing channel shall be associated with the newly created endpoint.] */
+            /* Codes_S_R_S_CONNECTION_01_128: [The lowest number outgoing channel shall be associated with the newly created endpoint.] */
             for (i = 0; i < connection->endpoint_count; i++)
             {
                 if (connection->endpoints[i]->outgoing_channel > i)
@@ -1823,9 +1873,9 @@
                 }
             }
 
-            /* Codes_SRS_CONNECTION_01_127: [On success, connection_create_endpoint shall return a non-NULL handle to the newly created endpoint.] */
+            /* Codes_S_R_S_CONNECTION_01_127: [On success, connection_create_endpoint shall return a non-NULL handle to the newly created endpoint.] */
             result = (ENDPOINT_HANDLE)malloc(sizeof(ENDPOINT_INSTANCE));
-            /* Codes_SRS_CONNECTION_01_196: [If memory cannot be allocated for the new endpoint, connection_create_endpoint shall fail and return NULL.] */
+            /* Codes_S_R_S_CONNECTION_01_196: [If memory cannot be allocated for the new endpoint, connection_create_endpoint shall fail and return NULL.] */
             if (result == NULL)
             {
                 LogError("Cannot allocate memory for endpoint");
@@ -1840,11 +1890,11 @@
                 result->outgoing_channel = (uint16_t)i;
                 result->connection = connection;
 
-                /* Codes_SRS_CONNECTION_01_197: [The newly created endpoint shall be added to the endpoints list, so that it can be tracked.] */
+                /* Codes_S_R_S_CONNECTION_01_197: [The newly created endpoint shall be added to the endpoints list, so that it can be tracked.] */
                 new_endpoints = (ENDPOINT_HANDLE*)realloc(connection->endpoints, sizeof(ENDPOINT_HANDLE) * (connection->endpoint_count + 1));
                 if (new_endpoints == NULL)
                 {
-                    /* Tests_SRS_CONNECTION_01_198: [If adding the endpoint to the endpoints list tracked by the connection fails, connection_create_endpoint shall fail and return NULL.] */
+                    /* Tests_S_R_S_CONNECTION_01_198: [If adding the endpoint to the endpoints list tracked by the connection fails, connection_create_endpoint shall fail and return NULL.] */
                     LogError("Cannot reallocate memory for connection endpoints");
                     free(result);
                     result = NULL;
@@ -1861,7 +1911,7 @@
                     connection->endpoints[i] = result;
                     connection->endpoint_count++;
 
-                    /* Codes_SRS_CONNECTION_01_112: [connection_create_endpoint shall create a new endpoint that can be used by a session.] */
+                    /* Codes_S_R_S_CONNECTION_01_112: [connection_create_endpoint shall create a new endpoint that can be used by a session.] */
                 }
             }
         }
@@ -1914,7 +1964,7 @@
     return result;
 }
 
-/* Codes_SRS_CONNECTION_01_129: [connection_destroy_endpoint shall free all resources associated with an endpoint created by connection_create_endpoint.] */
+/* Codes_S_R_S_CONNECTION_01_129: [connection_destroy_endpoint shall free all resources associated with an endpoint created by connection_create_endpoint.] */
 void connection_destroy_endpoint(ENDPOINT_HANDLE endpoint)
 {
     if (endpoint == NULL)
@@ -1934,8 +1984,8 @@
             }
         }
 
-        /* Codes_SRS_CONNECTION_01_130: [The outgoing channel associated with the endpoint shall be released by removing the endpoint from the endpoint list.] */
-        /* Codes_SRS_CONNECTION_01_131: [Any incoming channel number associated with the endpoint shall be released.] */
+        /* Codes_S_R_S_CONNECTION_01_130: [The outgoing channel associated with the endpoint shall be released by removing the endpoint from the endpoint list.] */
+        /* Codes_S_R_S_CONNECTION_01_131: [Any incoming channel number associated with the endpoint shall be released.] */
         if ((i < connection->endpoint_count) && (i > 0))
         {
             ENDPOINT_HANDLE* new_endpoints;
@@ -1960,12 +2010,12 @@
     }
 }
 
-/* Codes_SRS_CONNECTION_01_247: [connection_encode_frame shall send a frame for a certain endpoint.] */
+/* Codes_S_R_S_CONNECTION_01_247: [connection_encode_frame shall send a frame for a certain endpoint.] */
 int connection_encode_frame(ENDPOINT_HANDLE endpoint, AMQP_VALUE performative, PAYLOAD* payloads, size_t payload_count, ON_SEND_COMPLETE on_send_complete, void* callback_context)
 {
     int result;
 
-    /* Codes_SRS_CONNECTION_01_249: [If endpoint or performative are NULL, connection_encode_frame shall fail and return a non-zero value.] */
+    /* Codes_S_R_S_CONNECTION_01_249: [If endpoint or performative are NULL, connection_encode_frame shall fail and return a non-zero value.] */
     if ((endpoint == NULL) ||
         (performative == NULL))
     {
@@ -1978,7 +2028,7 @@
         CONNECTION_HANDLE connection = (CONNECTION_HANDLE)endpoint->connection;
         AMQP_FRAME_CODEC_HANDLE amqp_frame_codec = connection->amqp_frame_codec;
 
-        /* Codes_SRS_CONNECTION_01_254: [If connection_encode_frame is called before the connection is in the OPENED state, connection_encode_frame shall fail and return a non-zero value.] */
+        /* Codes_S_R_S_CONNECTION_01_254: [If connection_encode_frame is called before the connection is in the OPENED state, connection_encode_frame shall fail and return a non-zero value.] */
         if (connection->connection_state != CONNECTION_STATE_OPENED)
         {
             LogError("Connection not open");
@@ -1986,15 +2036,15 @@
         }
         else
         {
-            /* Codes_SRS_CONNECTION_01_255: [The payload size shall be computed based on all the payload chunks passed as argument in payloads.] */
-            /* Codes_SRS_CONNECTION_01_250: [connection_encode_frame shall initiate the frame send by calling amqp_frame_codec_begin_encode_frame.] */
-            /* Codes_SRS_CONNECTION_01_251: [The channel number passed to amqp_frame_codec_begin_encode_frame shall be the outgoing channel number associated with the endpoint by connection_create_endpoint.] */
-            /* Codes_SRS_CONNECTION_01_252: [The performative passed to amqp_frame_codec_begin_encode_frame shall be the performative argument of connection_encode_frame.] */
+            /* Codes_S_R_S_CONNECTION_01_255: [The payload size shall be computed based on all the payload chunks passed as argument in payloads.] */
+            /* Codes_S_R_S_CONNECTION_01_250: [connection_encode_frame shall initiate the frame send by calling amqp_frame_codec_begin_encode_frame.] */
+            /* Codes_S_R_S_CONNECTION_01_251: [The channel number passed to amqp_frame_codec_begin_encode_frame shall be the outgoing channel number associated with the endpoint by connection_create_endpoint.] */
+            /* Codes_S_R_S_CONNECTION_01_252: [The performative passed to amqp_frame_codec_begin_encode_frame shall be the performative argument of connection_encode_frame.] */
             connection->on_send_complete = on_send_complete;
             connection->on_send_complete_callback_context = callback_context;
             if (amqp_frame_codec_encode_frame(amqp_frame_codec, endpoint->outgoing_channel, performative, payloads, payload_count, on_bytes_encoded, connection) != 0)
             {
-                /* Codes_SRS_CONNECTION_01_253: [If amqp_frame_codec_begin_encode_frame or amqp_frame_codec_encode_payload_bytes fails, then connection_encode_frame shall fail and return a non-zero value.] */
+                /* Codes_S_R_S_CONNECTION_01_253: [If amqp_frame_codec_begin_encode_frame or amqp_frame_codec_encode_payload_bytes fails, then connection_encode_frame shall fail and return a non-zero value.] */
                 LogError("Encoding AMQP frame failed");
                 result = __FAILURE__;
             }
@@ -2012,7 +2062,7 @@
                 }
                 else
                 {
-                    /* Codes_SRS_CONNECTION_01_248: [On success it shall return 0.] */
+                    /* Codes_S_R_S_CONNECTION_01_248: [On success it shall return 0.] */
                     result = 0;
                 }
             }
@@ -2024,14 +2074,14 @@
 
 void connection_set_trace(CONNECTION_HANDLE connection, bool trace_on)
 {
-    /* Codes_SRS_CONNECTION_07_002: [If connection is NULL then connection_set_trace shall do nothing.] */
+    /* Codes_S_R_S_CONNECTION_07_002: [If connection is NULL then connection_set_trace shall do nothing.] */
     if (connection == NULL)
     {
         LogError("NULL connection");
     }
     else
     {
-        /* Codes_SRS_CONNECTION_07_001: [connection_set_trace shall set the ability to turn on and off trace logging.] */
+        /* Codes_S_R_S_CONNECTION_07_001: [connection_set_trace shall set the ability to turn on and off trace logging.] */
         connection->is_trace_on = trace_on ? 1 : 0;
     }
 }
@@ -2056,3 +2106,54 @@
 
     return result;
 }
+
+ON_CONNECTION_CLOSED_EVENT_SUBSCRIPTION_HANDLE connection_subscribe_on_connection_close_received(CONNECTION_HANDLE connection, ON_CONNECTION_CLOSE_RECEIVED on_connection_close_received, void* context)
+{
+    ON_CONNECTION_CLOSED_EVENT_SUBSCRIPTION_HANDLE result;
+
+    /* Codes_S_R_S_CONNECTION_01_279: [ `context` shall be allowed to be NULL. ]*/
+
+    /* Codes_S_R_S_CONNECTION_01_277: [ If `connection` is NULL, `connection_subscribe_on_connection_close_received` shall fail and return NULL. ]*/
+    if ((connection == NULL) ||
+        /* Codes_S_R_S_CONNECTION_01_278: [ If `on_connection_close_received` is NULL, `connection_subscribe_on_connection_close_received` shall fail and return NULL. ]*/
+        (on_connection_close_received == NULL))
+    {
+        LogError("Invalid arguments: connection = %p, on_connection_close_received = %p, context = %p",
+            connection, on_connection_close_received, context);
+        result = NULL;
+    }
+    else
+    {
+        if (connection->on_connection_close_received_event_subscription.on_connection_close_received != NULL)
+        {
+            /* Codes_S_R_S_CONNECTION_01_280: [ Only one subscription shall be allowed per connection, if a subsequent second even subscription is done while a subscription is active, `connection_subscribe_on_connection_close_received` shall fail and return NULL. ]*/
+            LogError("Already subscribed for on_connection_close_received events");
+            result = NULL;
+        }
+        else
+        {
+            /* Codes_S_R_S_CONNECTION_01_275: [ `connection_subscribe_on_connection_close_received` shall register the `on_connection_close_received` handler to be triggered whenever a CLOSE performative is received.. ]*/
+            connection->on_connection_close_received_event_subscription.on_connection_close_received = on_connection_close_received;
+            connection->on_connection_close_received_event_subscription.context = context;
+
+            /* Codes_S_R_S_CONNECTION_01_276: [ On success, `connection_subscribe_on_connection_close_received` shall return a non-NULL handle to the event subcription. ]*/
+            result = &connection->on_connection_close_received_event_subscription;
+        }
+    }
+
+    return result;
+}
+
+void connection_unsubscribe_on_connection_close_received(ON_CONNECTION_CLOSED_EVENT_SUBSCRIPTION_HANDLE event_subscription)
+{
+    if (event_subscription == NULL)
+    {
+        LogError("NULL event_subscription");
+    }
+    else
+    {
+        /* Codes_S_R_S_CONNECTION_01_281: [ `connection_unsubscribe_on_connection_close_received` shall remove the subscription for the connection closed event that was made by calling `connection_subscribe_on_connection_close_received`. ]*/
+        event_subscription->on_connection_close_received = NULL;
+        event_subscription->context = NULL;
+    }
+}
--- a/header_detect_io.c	Fri May 04 13:24:52 2018 -0700
+++ b/header_detect_io.c	Mon Jun 11 15:39:52 2018 -0700
@@ -132,7 +132,7 @@
     }
 }
 
-// This callback usage needs to be either verified and commented or integrated into 
+// This callback usage needs to be either verified and commented or integrated into
 // the state machine.
 static void unchecked_on_send_complete(void* context, IO_SEND_RESULT send_result)
 {
@@ -942,13 +942,13 @@
     sizeof(sasl_amqp_header_bytes)
 };
 
-const AMQP_HEADER header_detect_io_get_amqp_header(void)
+AMQP_HEADER header_detect_io_get_amqp_header(void)
 {
     /* Codes_SRS_HEADER_DETECT_IO_01_091: [ `header_detect_io_get_amqp_header` shall return a structure that should point to a buffer that contains the bytes { 'A', 'M', 'Q', 'P', 0, 1, 0, 0 }. ]*/
     return amqp_header;
 }
 
-const AMQP_HEADER header_detect_io_get_sasl_amqp_header(void)
+AMQP_HEADER header_detect_io_get_sasl_amqp_header(void)
 {
     /* Codes_SRS_HEADER_DETECT_IO_01_091: [ `header_detect_io_get_sasl_amqp_header` shall return a structure that should point to a buffer that contains the bytes { 'A', 'M', 'Q', 'P', 3, 1, 0, 0 }. ]*/
     return sasl_amqp_header;
--- a/link.c	Fri May 04 13:24:52 2018 -0700
+++ b/link.c	Mon Jun 11 15:39:52 2018 -0700
@@ -29,6 +29,12 @@
     tickcounter_ms_t timeout;
 } DELIVERY_INSTANCE;
 
+typedef struct ON_LINK_DETACH_EVENT_SUBSCRIPTION_TAG
+{
+    ON_LINK_DETACH_RECEIVED on_link_detach_received;
+    void* context;
+} ON_LINK_DETACH_EVENT_SUBSCRIPTION;
+
 typedef struct LINK_INSTANCE_TAG
 {
     SESSION_HANDLE session;
@@ -61,6 +67,7 @@
     uint32_t received_payload_size;
     delivery_number received_delivery_id;
     TICK_COUNTER_HANDLE tick_counter;
+    ON_LINK_DETACH_EVENT_SUBSCRIPTION on_link_detach_received_event_subscription;
 } LINK_INSTANCE;
 
 DEFINE_ASYNC_OPERATION_CONTEXT(DELIVERY_INSTANCE);
@@ -595,7 +602,6 @@
                     LogError("Failed sending detach frame");
                 }
             }
-
             /* Received a closing detach after we sent a non-closing detach. */
             else if (closed &&
                 ((link_instance->link_state == LINK_STATE_HALF_ATTACHED_ATTACH_SENT) || (link_instance->link_state == LINK_STATE_HALF_ATTACHED_ATTACH_RECEIVED)) &&
@@ -616,10 +622,16 @@
 
             if (detach_get_error(detach, &error) == 0)
             {
-                error_destroy(error);
-
                 remove_all_pending_deliveries(link_instance, true);
                 set_link_state(link_instance, LINK_STATE_ERROR);
+
+                // signal link detach received in order to handle cases like redirect
+                if (link_instance->on_link_detach_received_event_subscription.on_link_detach_received != NULL)
+                {
+                    link_instance->on_link_detach_received_event_subscription.on_link_detach_received(link_instance->on_link_detach_received_event_subscription.context, error);
+                }
+
+                error_destroy(error);
             }
             else 
             {
@@ -714,6 +726,8 @@
         result->received_payload = NULL;
         result->received_payload_size = 0;
         result->received_delivery_id = 0;
+        result->on_link_detach_received_event_subscription.on_link_detach_received = NULL;
+        result->on_link_detach_received_event_subscription.context = NULL;
 
         result->tick_counter = tickcounter_create();
         if (result->tick_counter == NULL)
@@ -797,6 +811,8 @@
         result->received_delivery_id = 0;
         result->source = amqpvalue_clone(target);
         result->target = amqpvalue_clone(source);
+        result->on_link_detach_received_event_subscription.on_link_detach_received = NULL;
+        result->on_link_detach_received_event_subscription.context = NULL;
 
         if (role == role_sender)
         {
@@ -862,7 +878,7 @@
         tickcounter_destroy(link->tick_counter);
 
         link->on_link_state_changed = NULL;
-        (void)link_detach(link, true);
+        (void)link_detach(link, true, NULL, NULL, NULL);
         session_destroy_link_endpoint(link->link_endpoint);
         amqpvalue_destroy(link->source);
         amqpvalue_destroy(link->target);
@@ -1162,10 +1178,14 @@
     return result;
 }
 
-int link_detach(LINK_HANDLE link, bool close)
+int link_detach(LINK_HANDLE link, bool close, const char* error_condition, const char* error_description, AMQP_VALUE info)
 {
     int result;
 
+    (void)error_condition;
+    (void)error_description;
+    (void)info;
+
     if (link == NULL)
     {
         LogError("NULL link");
@@ -1177,12 +1197,45 @@
     }
     else
     {
+        ERROR_HANDLE error;
+
+        if (error_condition != NULL)
+        {
+            error = error_create(error_condition);
+            if (error == NULL)
+            {
+                LogInfo("Cannot create error for detach, detaching without error anyhow");
+            }
+            else
+            {
+                if (error_description != NULL)
+                {
+                    if (error_set_description(error, error_description) != 0)
+                    {
+                        LogInfo("Cannot set error description on detach error, detaching anyhow");
+                    }
+                }
+
+                if (info != NULL)
+                {
+                    if (error_set_info(error, info) != 0)
+                    {
+                        LogInfo("Cannot set info map on detach error, detaching anyhow");
+                    }
+                }
+            }
+        }
+        else
+        {
+            error = NULL;
+        }
+
         switch (link->link_state)
         {
         case LINK_STATE_HALF_ATTACHED_ATTACH_SENT:
         case LINK_STATE_HALF_ATTACHED_ATTACH_RECEIVED:
             /* Sending detach when remote is not yet attached */
-            if (send_detach(link, close, NULL) != 0)
+            if (send_detach(link, close, error) != 0)
             {
                 LogError("Sending detach frame failed");
                 result = __FAILURE__;
@@ -1196,7 +1249,7 @@
 
         case LINK_STATE_ATTACHED:
             /* Send detach and wait for remote to respond */
-            if (send_detach(link, close, NULL) != 0)
+            if (send_detach(link, close, error) != 0)
             {
                 LogError("Sending detach frame failed");
                 result = __FAILURE__;
@@ -1219,6 +1272,11 @@
             result = __FAILURE__;
             break;
         }
+
+        if (error != NULL)
+        {
+            error_destroy(error);
+        }
     }
 
     return result;
@@ -1550,3 +1608,46 @@
         }
     }
 }
+
+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)
+{
+    ON_LINK_DETACH_EVENT_SUBSCRIPTION_HANDLE result;
+
+    if ((link == NULL) ||
+        (on_link_detach_received == NULL))
+    {
+        LogError("Invalid arguments: link = %p, on_link_detach_received = %p, context = %p",
+            link, on_link_detach_received, context);
+        result = NULL;
+    }
+    else
+    {
+        if (link->on_link_detach_received_event_subscription.on_link_detach_received != NULL)
+        {
+            LogError("Already subscribed for on_link_detach_received events");
+            result = NULL;
+        }
+        else
+        {
+            link->on_link_detach_received_event_subscription.on_link_detach_received = on_link_detach_received;
+            link->on_link_detach_received_event_subscription.context = context;
+
+            result = &link->on_link_detach_received_event_subscription;
+        }
+    }
+
+    return result;
+}
+
+void link_unsubscribe_on_link_detach_received(ON_LINK_DETACH_EVENT_SUBSCRIPTION_HANDLE event_subscription)
+{
+    if (event_subscription == NULL)
+    {
+        LogError("NULL event_subscription");
+    }
+    else
+    {
+        event_subscription->on_link_detach_received = NULL;
+        event_subscription->context = NULL;
+    }
+}
--- a/message_receiver.c	Fri May 04 13:24:52 2018 -0700
+++ b/message_receiver.c	Mon Jun 11 15:39:52 2018 -0700
@@ -396,7 +396,7 @@
         {
             set_message_receiver_state(message_receiver, MESSAGE_RECEIVER_STATE_CLOSING);
 
-            if (link_detach(message_receiver->link, true) != 0)
+            if (link_detach(message_receiver->link, true, NULL, NULL, NULL) != 0)
             {
                 LogError("link detach failed");
                 result = __FAILURE__;
--- a/message_sender.c	Fri May 04 13:24:52 2018 -0700
+++ b/message_sender.c	Mon Jun 11 15:39:52 2018 -0700
@@ -800,7 +800,7 @@
             (message_sender->message_sender_state == MESSAGE_SENDER_STATE_OPEN))
         {
             set_message_sender_state(message_sender, MESSAGE_SENDER_STATE_CLOSING);
-            if (link_detach(message_sender->link, true) != 0)
+            if (link_detach(message_sender->link, true, NULL, NULL, NULL) != 0)
             {
                 LogError("Detaching link failed");
                 result = __FAILURE__;
--- a/saslclientio.c	Fri May 04 13:24:52 2018 -0700
+++ b/saslclientio.c	Mon Jun 11 15:39:52 2018 -0700
@@ -33,6 +33,12 @@
     SASL_HEADER_EXCHANGE_HEADER_RCVD, \
     SASL_HEADER_EXCHANGE_HEADER_EXCH
 
+// Suppress unused function warning for SASL_HEADER_EXCHANGE_STATEstrings
+#ifdef NO_LOGGING
+#define ENUM_TO_STRING_UNUSED
+#include "azure_c_shared_utility/macro_utils.h"
+#endif
+
 DEFINE_LOCAL_ENUM(SASL_HEADER_EXCHANGE_STATE, SASL_HEADER_EXCHANGE_STATE_VALUES)
 
 #define SASL_CLIENT_NEGOTIATION_STATE_VALUES \
@@ -144,7 +150,7 @@
     }
 }
 
-// This callback usage needs to be either verified and commented or integrated into 
+// This callback usage needs to be either verified and commented or integrated into
 // the state machine.
 static void unchecked_on_send_complete(void* context, IO_SEND_RESULT send_result)
 {
@@ -255,6 +261,7 @@
     }
 }
 
+#ifndef NO_LOGGING
 static const char* get_frame_type_as_string(AMQP_VALUE descriptor)
 {
     const char* result;
@@ -286,6 +293,7 @@
 
     return result;
 }
+#endif // NO_LOGGING
 
 static void log_incoming_frame(AMQP_VALUE performative)
 {
@@ -400,7 +408,7 @@
                     LogError("Invalid SASL header exchange state: %s", ENUM_TO_STRING(SASL_HEADER_EXCHANGE_STATE, sasl_client_io_instance->sasl_header_exchange_state));
                     result = __FAILURE__;
                     break;
-                
+
                 case SASL_HEADER_EXCHANGE_HEADER_SENT:
                     /* from this point on we need to decode SASL frames */
                     sasl_client_io_instance->sasl_header_exchange_state = SASL_HEADER_EXCHANGE_HEADER_EXCH;
@@ -1096,7 +1104,7 @@
             }
         }
     }
-    
+
     return result;
 }
 
--- a/session.c	Fri May 04 13:24:52 2018 -0700
+++ b/session.c	Mon Jun 11 15:39:52 2018 -0700
@@ -5,11 +5,17 @@
 #include <string.h>
 #include "azure_c_shared_utility/optimize_size.h"
 #include "azure_c_shared_utility/gballoc.h"
-#include "azure_c_shared_utility/xlogging.h"
 #include "azure_uamqp_c/session.h"
 #include "azure_uamqp_c/connection.h"
 #include "azure_uamqp_c/amqp_definitions.h"
 
+typedef enum LINK_ENDPOINT_STATE_TAG
+{
+    LINK_ENDPOINT_STATE_NOT_ATTACHED,
+    LINK_ENDPOINT_STATE_ATTACHED,
+    LINK_ENDPOINT_STATE_DETACHING
+} LINK_ENDPOINT_STATE;
+
 typedef struct LINK_ENDPOINT_INSTANCE_TAG
 {
     char* name;
@@ -20,6 +26,7 @@
     ON_SESSION_FLOW_ON on_session_flow_on;
     void* callback_context;
     SESSION_HANDLE session;
+    LINK_ENDPOINT_STATE link_endpoint_state;
 } LINK_ENDPOINT_INSTANCE;
 
 typedef struct SESSION_INSTANCE_TAG
@@ -36,7 +43,7 @@
     ON_LINK_ATTACHED on_link_attached;
     void* on_link_attached_callback_context;
 
-    /* Codes_SRS_SESSION_01_016: [next-outgoing-id The next-outgoing-id is the transfer-id to assign to the next transfer frame.] */
+    /* 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.] */
     transfer_number next_outgoing_id;
     transfer_number next_incoming_id;
     uint32_t desired_incoming_window;
@@ -45,15 +52,69 @@
     handle handle_max;
     uint32_t remote_incoming_window;
     uint32_t remote_outgoing_window;
-    int is_underlying_connection_open : 1;
+    unsigned int is_underlying_connection_open : 1;
 } SESSION_INSTANCE;
 
 #define UNDERLYING_CONNECTION_NOT_OPEN 0
-#define UNDERLYING_CONNECTION_OPEN -1
+#define UNDERLYING_CONNECTION_OPEN 1
+
+static void remove_link_endpoint(LINK_ENDPOINT_HANDLE link_endpoint)
+{
+    if (link_endpoint != NULL)
+    {
+        LINK_ENDPOINT_INSTANCE* endpoint_instance = (LINK_ENDPOINT_INSTANCE*)link_endpoint;
+        SESSION_INSTANCE* session_instance = endpoint_instance->session;
+        uint32_t i;
+
+        for (i = 0; i < session_instance->link_endpoint_count; i++)
+        {
+            if (session_instance->link_endpoints[i] == link_endpoint)
+            {
+                break;
+            }
+        }
+
+        if (i < session_instance->link_endpoint_count)
+        {
+            LINK_ENDPOINT_INSTANCE** new_endpoints;
+
+            if (i < (session_instance->link_endpoint_count - 1))
+            {
+                (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*));
+            }
+
+            session_instance->link_endpoint_count--;
+
+            if (session_instance->link_endpoint_count == 0)
+            {
+                free(session_instance->link_endpoints);
+                session_instance->link_endpoints = NULL;
+            }
+            else
+            {
+                new_endpoints = (LINK_ENDPOINT_INSTANCE**)realloc(session_instance->link_endpoints, sizeof(LINK_ENDPOINT_INSTANCE*) * session_instance->link_endpoint_count);
+                if (new_endpoints != NULL)
+                {
+                    session_instance->link_endpoints = new_endpoints;
+                }
+            }
+        }
+    }
+}
+
+static void free_link_endpoint(LINK_ENDPOINT_HANDLE link_endpoint)
+{
+    if (link_endpoint->name != NULL)
+    {
+        free(link_endpoint->name);
+    }
+
+    free(link_endpoint);
+}
 
 static void session_set_state(SESSION_INSTANCE* session_instance, SESSION_STATE session_state)
 {
-    uint64_t i;
+    uint32_t i;
 
     session_instance->previous_session_state = session_instance->session_state;
     session_instance->session_state = session_state;
@@ -62,7 +123,10 @@
     {
         if (session_instance->link_endpoints[i]->on_session_state_changed != NULL)
         {
-            session_instance->link_endpoints[i]->on_session_state_changed(session_instance->link_endpoints[i]->callback_context, session_state, session_instance->previous_session_state);
+            if (session_instance->link_endpoints[i]->link_endpoint_state != LINK_ENDPOINT_STATE_DETACHING)
+            {
+                session_instance->link_endpoints[i]->on_session_state_changed(session_instance->link_endpoints[i]->callback_context, session_state, session_instance->previous_session_state);
+            }
         }
     }
 }
@@ -119,7 +183,7 @@
     {
         /* fatal error */
         session_set_state(session_instance, SESSION_STATE_DISCARDING);
-        (void)connection_close(session_instance->connection, "amqp:internal-error", "Cannot allocate error handle to end session");
+        (void)connection_close(session_instance->connection, "amqp:internal-error", "Cannot allocate error handle to end session", NULL);
     }
     else
     {
@@ -128,7 +192,7 @@
         {
             /* fatal error */
             session_set_state(session_instance, SESSION_STATE_DISCARDING);
-            (void)connection_close(session_instance->connection, "amqp:internal-error", "Cannot allocate error handle to end session");
+            (void)connection_close(session_instance->connection, "amqp:internal-error", "Cannot allocate error handle to end session", NULL);
         }
         else
         {
@@ -293,7 +357,7 @@
 {
     SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)context;
 
-    /* Codes_SRS_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.] */
+    /* 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.] */
     if ((new_connection_state == CONNECTION_STATE_OPENED) && (previous_connection_state != CONNECTION_STATE_OPENED) && (session_instance->session_state == SESSION_STATE_UNMAPPED))
     {
         if (send_begin(session_instance) == 0)
@@ -301,12 +365,12 @@
             session_set_state(session_instance, SESSION_STATE_BEGIN_SENT);
         }
     }
-    /* Codes_SRS_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.] */
+    /* 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.] */
     else if ((new_connection_state == CONNECTION_STATE_CLOSE_RCVD) || (new_connection_state == CONNECTION_STATE_END))
     {
         session_set_state(session_instance, SESSION_STATE_DISCARDING);
     }
-    /* Codes_SRS_SESSION_09_001: [If the new connection state is ERROR, the state shall be switched to ERROR.] */
+    /* Codes_S_R_S_SESSION_09_001: [If the new connection state is ERROR, the state shall be switched to ERROR.] */
     else if (new_connection_state == CONNECTION_STATE_ERROR)
     {
         session_set_state(session_instance, SESSION_STATE_ERROR);
@@ -324,7 +388,7 @@
 
         if (amqpvalue_get_begin(performative, &begin_handle) != 0)
         {
-            connection_close(session_instance->connection, "amqp:decode-error", "Cannot decode BEGIN frame");
+            connection_close(session_instance->connection, "amqp:decode-error", "Cannot decode BEGIN frame", NULL);
         }
         else
         {
@@ -334,7 +398,7 @@
                 /* error */
                 begin_destroy(begin_handle);
                 session_set_state(session_instance, SESSION_STATE_DISCARDING);
-                connection_close(session_instance->connection, "amqp:decode-error", "Cannot get incoming windows and next outgoing id");
+                connection_close(session_instance->connection, "amqp:decode-error", "Cannot get incoming windows and next outgoing id", NULL);
             }
             else
             {
@@ -349,7 +413,7 @@
                     session_set_state(session_instance, SESSION_STATE_BEGIN_RCVD);
                     if (send_begin(session_instance) != 0)
                     {
-                        connection_close(session_instance->connection, "amqp:internal-error", "Failed sending BEGIN frame");
+                        connection_close(session_instance->connection, "amqp:internal-error", "Failed sending BEGIN frame", NULL);
                         session_set_state(session_instance, SESSION_STATE_DISCARDING);
                     }
                     else
@@ -387,7 +451,7 @@
             {
                 end_session_with_error(session_instance, "amqp:decode-error", "Cannot get link source from ATTACH frame");
             }
-            else  if (attach_get_target(attach_handle, &target) != 0)
+            else if (attach_get_target(attach_handle, &target) != 0)
             {
                 end_session_with_error(session_instance, "amqp:decode-error", "Cannot get link target from ATTACH frame");
             }
@@ -410,9 +474,12 @@
                         }
                         else
                         {
+                            new_link_endpoint->link_endpoint_state = LINK_ENDPOINT_STATE_ATTACHED;
+
                             if (!session_instance->on_link_attached(session_instance->on_link_attached_callback_context, new_link_endpoint, name, role, source, target))
                             {
-                                session_destroy_link_endpoint(new_link_endpoint);
+                                remove_link_endpoint(new_link_endpoint);
+                                free_link_endpoint(new_link_endpoint);
                                 new_link_endpoint = NULL;
                             }
                             else
@@ -433,6 +500,8 @@
                     }
                     else
                     {
+                        link_endpoint->link_endpoint_state = LINK_ENDPOINT_STATE_ATTACHED;
+
                         link_endpoint->frame_received_callback(link_endpoint->callback_context, performative, payload_size, payload_bytes);
                     }
                 }
@@ -470,7 +539,16 @@
                 }
                 else
                 {
-                    link_endpoint->frame_received_callback(link_endpoint->callback_context, performative, payload_size, payload_bytes);
+                    if (link_endpoint->link_endpoint_state != LINK_ENDPOINT_STATE_DETACHING)
+                    {
+                        link_endpoint->frame_received_callback(link_endpoint->callback_context, performative, payload_size, payload_bytes);
+                    }
+                    else
+                    {
+                        /* remove the link endpoint */
+                        remove_link_endpoint(link_endpoint);
+                        free_link_endpoint(link_endpoint);
+                    }
                 }
             }
         }
@@ -492,8 +570,8 @@
             if (flow_get_next_incoming_id(flow_handle, &flow_next_incoming_id) != 0)
             {
                 /*
-                If the next-incoming-id field of the flow frame is not set, 
-                then remote-incomingwindow is computed as follows: 
+                If the next-incoming-id field of the flow frame is not set,
+                then remote-incomingwindow is computed as follows:
                 initial-outgoing-id(endpoint) + incoming-window(flow) - next-outgoing-id(endpoint)
                 */
                 flow_next_incoming_id = session_instance->next_outgoing_id;
@@ -522,7 +600,10 @@
 
                 if (link_endpoint_instance != NULL)
                 {
-                    link_endpoint_instance->frame_received_callback(link_endpoint_instance->callback_context, performative, payload_size, payload_bytes);
+                    if (link_endpoint_instance->link_endpoint_state != LINK_ENDPOINT_STATE_DETACHING)
+                    {
+                        link_endpoint_instance->frame_received_callback(link_endpoint_instance->callback_context, performative, payload_size, payload_bytes);
+                    }
                 }
 
                 i = 0;
@@ -574,7 +655,10 @@
                 }
                 else
                 {
-                    link_endpoint->frame_received_callback(link_endpoint->callback_context, performative, payload_size, payload_bytes);
+                    if (link_endpoint->link_endpoint_state != LINK_ENDPOINT_STATE_DETACHING)
+                    {
+                        link_endpoint->frame_received_callback(link_endpoint->callback_context, performative, payload_size, payload_bytes);
+                    }
                 }
 
                 if (session_instance->incoming_window == 0)
@@ -592,7 +676,10 @@
         for (i = 0; i < session_instance->link_endpoint_count; i++)
         {
             LINK_ENDPOINT_INSTANCE* link_endpoint = session_instance->link_endpoints[i];
-            link_endpoint->frame_received_callback(link_endpoint->callback_context, performative, payload_size, payload_bytes);
+            if (link_endpoint->link_endpoint_state != LINK_ENDPOINT_STATE_DETACHING)
+            {
+                link_endpoint->frame_received_callback(link_endpoint->callback_context, performative, payload_size, payload_bytes);
+            }
         }
     }
     else if (is_end_type_by_descriptor(descriptor))
@@ -613,7 +700,7 @@
                 if (send_end_frame(session_instance, NULL) != 0)
                 {
                     /* fatal error */
-                    (void)connection_close(session_instance->connection, "amqp:internal-error", "Cannot send END frame.");
+                    (void)connection_close(session_instance->connection, "amqp:internal-error", "Cannot send END frame.", NULL);
                 }
 
                 session_set_state(session_instance, SESSION_STATE_DISCARDING);
@@ -628,14 +715,14 @@
 
     if (connection == NULL)
     {
-        /* Codes_SRS_SESSION_01_031: [If connection is NULL, session_create shall fail and return NULL.] */
+        /* Codes_S_R_S_SESSION_01_031: [If connection is NULL, session_create shall fail and return NULL.] */
         result = NULL;
     }
     else
     {
-        /* Codes_SRS_SESSION_01_030: [session_create shall create a new session instance and return a non-NULL handle to it.] */
+        /* Codes_S_R_S_SESSION_01_030: [session_create shall create a new session instance and return a non-NULL handle to it.] */
         result = (SESSION_INSTANCE*)malloc(sizeof(SESSION_INSTANCE));
-        /* Codes_SRS_SESSION_01_042: [If allocating memory for the session fails, session_create shall fail and return NULL.] */
+        /* Codes_S_R_S_SESSION_01_042: [If allocating memory for the session fails, session_create shall fail and return NULL.] */
         if (result != NULL)
         {
             result->connection = connection;
@@ -643,8 +730,8 @@
             result->link_endpoint_count = 0;
             result->handle_max = 4294967295u;
 
-            /* Codes_SRS_SESSION_01_057: [The delivery ids shall be assigned starting at 0.] */
-            /* Codes_SRS_SESSION_01_017: [The nextoutgoing-id MAY be initialized to an arbitrary value ] */
+            /* Codes_S_R_S_SESSION_01_057: [The delivery ids shall be assigned starting at 0.] */
+            /* Codes_S_R_S_SESSION_01_017: [The nextoutgoing-id MAY be initialized to an arbitrary value ] */
             result->next_outgoing_id = 0;
 
             result->desired_incoming_window = 1;
@@ -659,11 +746,11 @@
             result->on_link_attached = on_link_attached;
             result->on_link_attached_callback_context = callback_context;
 
-            /* Codes_SRS_SESSION_01_032: [session_create shall create a new session endpoint by calling connection_create_endpoint.] */
+            /* Codes_S_R_S_SESSION_01_032: [session_create shall create a new session endpoint by calling connection_create_endpoint.] */
             result->endpoint = connection_create_endpoint(connection);
             if (result->endpoint == NULL)
             {
-                /* Codes_SRS_SESSION_01_033: [If connection_create_endpoint fails, session_create shall fail and return NULL.] */
+                /* Codes_S_R_S_SESSION_01_033: [If connection_create_endpoint fails, session_create shall fail and return NULL.] */
                 free(result);
                 result = NULL;
             }
@@ -719,15 +806,15 @@
 
 void session_destroy(SESSION_HANDLE session)
 {
-    /* Codes_SRS_SESSION_01_036: [If session is NULL, session_destroy shall do nothing.] */
+    /* Codes_S_R_S_SESSION_01_036: [If session is NULL, session_destroy shall do nothing.] */
     if (session != NULL)
     {
         SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)session;
 
         session_end(session, NULL, NULL);
 
-        /* Codes_SRS_SESSION_01_034: [session_destroy shall free all resources allocated by session_create.] */
-        /* Codes_SRS_SESSION_01_035: [The endpoint created in session_create shall be freed by calling connection_destroy_endpoint.] */
+        /* Codes_S_R_S_SESSION_01_034: [session_destroy shall free all resources allocated by session_create.] */
+        /* Codes_S_R_S_SESSION_01_035: [The endpoint created in session_create shall be freed by calling connection_destroy_endpoint.] */
         connection_destroy_endpoint(session_instance->endpoint);
         if (session_instance->link_endpoints != NULL)
         {
@@ -790,6 +877,7 @@
     else
     {
         SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)session;
+        size_t i;
 
         if ((session_instance->session_state != SESSION_STATE_UNMAPPED) &&
             (session_instance->session_state != SESSION_STATE_DISCARDING))
@@ -835,6 +923,14 @@
         {
             result = 0;
         }
+
+        // all link endpoints are destroyed when the session end happens
+        for (i = 0; i < session_instance->link_endpoint_count; i++)
+        {
+            free_link_endpoint(session_instance->link_endpoints[i]);
+        }
+
+        session_instance->link_endpoint_count = 0;
     }
 
     return result;
@@ -968,7 +1064,7 @@
 {
     LINK_ENDPOINT_INSTANCE* result;
 
-    /* Codes_SRS_SESSION_01_044: [If session, name or frame_received_callback is NULL, session_create_link_endpoint shall fail and return NULL.] */
+    /* 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.] */
     if ((session == NULL) ||
         (name == NULL))
     {
@@ -976,14 +1072,14 @@
     }
     else
     {
-        /* Codes_SRS_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.] */
+        /* 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.] */
         SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)session;
 
         result = (LINK_ENDPOINT_INSTANCE*)malloc(sizeof(LINK_ENDPOINT_INSTANCE));
-        /* Codes_SRS_SESSION_01_045: [If allocating memory for the link endpoint fails, session_create_link_endpoint shall fail and return NULL.] */
+        /* Codes_S_R_S_SESSION_01_045: [If allocating memory for the link endpoint fails, session_create_link_endpoint shall fail and return NULL.] */
         if (result != NULL)
         {
-            /* Codes_SRS_SESSION_01_046: [An unused handle shall be assigned to the link endpoint.] */
+            /* Codes_S_R_S_SESSION_01_046: [An unused handle shall be assigned to the link endpoint.] */
             handle selected_handle = 0;
             size_t i;
             size_t name_length;
@@ -1004,11 +1100,12 @@
             result->callback_context = NULL;
             result->output_handle = selected_handle;
             result->input_handle = 0xFFFFFFFF;
+            result->link_endpoint_state = LINK_ENDPOINT_STATE_NOT_ATTACHED;
             name_length = strlen(name);
             result->name = (char*)malloc(name_length + 1);
             if (result->name == NULL)
             {
-                /* Codes_SRS_SESSION_01_045: [If allocating memory for the link endpoint fails, session_create_link_endpoint shall fail and return NULL.] */
+                /* Codes_S_R_S_SESSION_01_045: [If allocating memory for the link endpoint fails, session_create_link_endpoint shall fail and return NULL.] */
                 free(result);
                 result = NULL;
             }
@@ -1021,7 +1118,7 @@
                 new_link_endpoints = (LINK_ENDPOINT_INSTANCE**)realloc(session_instance->link_endpoints, sizeof(LINK_ENDPOINT_INSTANCE*) * (session_instance->link_endpoint_count + 1));
                 if (new_link_endpoints == NULL)
                 {
-                    /* Codes_SRS_SESSION_01_045: [If allocating memory for the link endpoint fails, session_create_link_endpoint shall fail and return NULL.] */
+                    /* Codes_S_R_S_SESSION_01_045: [If allocating memory for the link endpoint fails, session_create_link_endpoint shall fail and return NULL.] */
                     free(result->name);
                     free(result);
                     result = NULL;
@@ -1047,54 +1144,19 @@
 
 void session_destroy_link_endpoint(LINK_ENDPOINT_HANDLE link_endpoint)
 {
-    /* Codes_SRS_SESSION_01_050: [If link_endpoint is NULL, session_destroy_link_endpoint shall do nothing.] */
     if (link_endpoint != NULL)
     {
         LINK_ENDPOINT_INSTANCE* endpoint_instance = (LINK_ENDPOINT_INSTANCE*)link_endpoint;
-        SESSION_INSTANCE* session_instance = endpoint_instance->session;
-        uint64_t i;
 
-        /* Codes_SRS_SESSION_01_049: [session_destroy_link_endpoint shall free all resources associated with the endpoint.] */
-        for (i = 0; i < session_instance->link_endpoint_count; i++)
-        {
-            if (session_instance->link_endpoints[i] == link_endpoint)
-            {
-                break;
-            }
-        }
-
-        if (i < session_instance->link_endpoint_count)
+        if (endpoint_instance->link_endpoint_state == LINK_ENDPOINT_STATE_ATTACHED)
         {
-            LINK_ENDPOINT_INSTANCE** new_endpoints;
-
-            if (i < (session_instance->link_endpoint_count - 1))
-            {
-                (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*));
-            }
-
-            session_instance->link_endpoint_count--;
-
-            if (session_instance->link_endpoint_count == 0)
-            {
-                free(session_instance->link_endpoints);
-                session_instance->link_endpoints = NULL;
-            }
-            else
-            {
-                new_endpoints = (LINK_ENDPOINT_INSTANCE**)realloc(session_instance->link_endpoints, sizeof(LINK_ENDPOINT_INSTANCE*) * session_instance->link_endpoint_count);
-                if (new_endpoints != NULL)
-                {
-                    session_instance->link_endpoints = new_endpoints;
-                }
-            }
+            endpoint_instance->link_endpoint_state = LINK_ENDPOINT_STATE_DETACHING;
         }
-
-        if (endpoint_instance->name != NULL)
+        else
         {
-            free(endpoint_instance->name);
+            remove_link_endpoint(link_endpoint);
+            free_link_endpoint(link_endpoint);
         }
-
-        free(endpoint_instance);
     }
 }
 
@@ -1113,6 +1175,7 @@
         link_endpoint->on_session_state_changed = on_session_state_changed;
         link_endpoint->on_session_flow_on = on_session_flow_on;
         link_endpoint->callback_context = context;
+        link_endpoint->link_endpoint_state = LINK_ENDPOINT_STATE_NOT_ATTACHED;
 
         if (link_endpoint->on_session_state_changed != NULL)
         {
@@ -1333,12 +1396,12 @@
     return result;
 }
 
-/* Codes_SRS_SESSION_01_051: [session_send_transfer shall send a transfer frame with the performative indicated in the transfer argument.] */
+/* Codes_S_R_S_SESSION_01_051: [session_send_transfer shall send a transfer frame with the performative indicated in the transfer argument.] */
 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)
 {
     SESSION_SEND_TRANSFER_RESULT result;
 
-    /* Codes_SRS_SESSION_01_054: [If link_endpoint or transfer is NULL, session_send_transfer shall fail and return a non-zero value.] */
+    /* 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.] */
     if ((link_endpoint == NULL) ||
         (transfer == NULL))
     {
@@ -1349,7 +1412,7 @@
         LINK_ENDPOINT_INSTANCE* link_endpoint_instance = (LINK_ENDPOINT_INSTANCE*)link_endpoint;
         SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)link_endpoint_instance->session;
 
-        /* Codes_SRS_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.] */
+        /* 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.] */
         if (session_instance->session_state != SESSION_STATE_MAPPED)
         {
             result = SESSION_SEND_TRANSFER_ERROR;
@@ -1383,14 +1446,14 @@
                 }
                 else
                 {
-                    /* Codes_SRS_SESSION_01_012: [The session endpoint assigns each outgoing transfer frame an implicit transfer-id from a session scoped sequence.] */
-                    /* Codes_SRS_SESSION_01_027: [sending a transfer Upon sending a transfer, the sending endpoint will increment its next-outgoing-id] */
+                    /* Codes_S_R_S_SESSION_01_012: [The session endpoint assigns each outgoing transfer frame an implicit transfer-id from a session scoped sequence.] */
+                    /* Codes_S_R_S_SESSION_01_027: [sending a transfer Upon sending a transfer, the sending endpoint will increment its next-outgoing-id] */
                     *delivery_id = session_instance->next_outgoing_id;
                     if ((transfer_set_handle(transfer, link_endpoint_instance->output_handle) != 0) ||
                         (transfer_set_delivery_id(transfer, *delivery_id) != 0) ||
                         (transfer_set_more(transfer, false) != 0))
                     {
-                        /* Codes_SRS_SESSION_01_058: [When any other error occurs, session_send_transfer shall fail and return a non-zero value.] */
+                        /* Codes_S_R_S_SESSION_01_058: [When any other error occurs, session_send_transfer shall fail and return a non-zero value.] */
                         result = SESSION_SEND_TRANSFER_ERROR;
                     }
                     else
@@ -1400,7 +1463,7 @@
                         transfer_value = amqpvalue_create_transfer(transfer);
                         if (transfer_value == NULL)
                         {
-                            /* Codes_SRS_SESSION_01_058: [When any other error occurs, session_send_transfer shall fail and return a non-zero value.] */
+                            /* Codes_S_R_S_SESSION_01_058: [When any other error occurs, session_send_transfer shall fail and return a non-zero value.] */
                             result = SESSION_SEND_TRANSFER_ERROR;
                         }
                         else
@@ -1427,20 +1490,20 @@
 
                                 if (available_frame_size >= payload_size)
                                 {
-                                    /* Codes_SRS_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.] */
+                                    /* 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.] */
                                     if (connection_encode_frame(session_instance->endpoint, transfer_value, payloads, payload_count, on_send_complete, callback_context) != 0)
                                     {
-                                        /* Codes_SRS_SESSION_01_056: [If connection_encode_frame fails then session_send_transfer shall fail and return a non-zero value.] */
+                                        /* Codes_S_R_S_SESSION_01_056: [If connection_encode_frame fails then session_send_transfer shall fail and return a non-zero value.] */
                                         result = SESSION_SEND_TRANSFER_ERROR;
                                     }
                                     else
                                     {
-                                        /* Codes_SRS_SESSION_01_018: [is incremented after each successive transfer according to RFC-1982 [RFC1982] serial number arithmetic.] */
+                                        /* Codes_S_R_S_SESSION_01_018: [is incremented after each successive transfer according to RFC-1982 [RFC1982] serial number arithmetic.] */
                                         session_instance->next_outgoing_id++;
                                         session_instance->remote_incoming_window--;
                                         session_instance->outgoing_window--;
 
-                                        /* Codes_SRS_SESSION_01_053: [On success, session_send_transfer shall return 0.] */
+                                        /* Codes_S_R_S_SESSION_01_053: [On success, session_send_transfer shall return 0.] */
                                         result = SESSION_SEND_TRANSFER_OK;
                                     }
                                 }
@@ -1556,7 +1619,7 @@
                                     }
                                     else
                                     {
-                                        /* Codes_SRS_SESSION_01_018: [is incremented after each successive transfer according to RFC-1982 [RFC1982] serial number arithmetic.] */
+                                        /* Codes_S_R_S_SESSION_01_018: [is incremented after each successive transfer according to RFC-1982 [RFC1982] serial number arithmetic.] */
                                         session_instance->next_outgoing_id++;
                                         session_instance->remote_incoming_window--;
                                         session_instance->outgoing_window--;