A small memory footprint AMQP implimentation
Dependents: iothub_client_sample_amqp remote_monitoring simplesample_amqp
Diff: connection.c
- Revision:
- 41:0e723f9cbd89
- Parent:
- 38:7631b92cc772
- Child:
- 43:4c1e4e94cdd3
--- a/connection.c Mon Mar 05 17:41:28 2018 -0800 +++ b/connection.c Tue Mar 20 10:29:38 2018 -0700 @@ -12,6 +12,7 @@ #include "azure_uamqp_c/connection.h" #include "azure_uamqp_c/frame_codec.h" +#include "azure_uamqp_c/amqpvalue.h" #include "azure_uamqp_c/amqp_frame_codec.h" #include "azure_uamqp_c/amqp_definitions.h" #include "azure_uamqp_c/amqpvalue_to_string.h" @@ -73,6 +74,7 @@ double idle_timeout_empty_frame_send_ratio; tickcounter_ms_t last_frame_received_time; tickcounter_ms_t last_frame_sent_time; + fields properties; unsigned int is_underlying_io_open : 1; unsigned int idle_timeout_specified : 1; @@ -356,6 +358,22 @@ 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).] */ + 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.] */ + (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.] */ + if (xio_close(connection->io, NULL, NULL) != 0) + { + LogError("xio_close failed"); + } + + connection_set_state(connection, CONNECTION_STATE_END); + result = __FAILURE__; + } else { AMQP_VALUE open_performative_value = amqpvalue_create_open(open_performative); @@ -1182,6 +1200,7 @@ connection->endpoints = NULL; connection->header_bytes_received = 0; connection->is_remote_frame_received = 0; + connection->properties = NULL; connection->is_underlying_io_open = 0; connection->remote_max_frame_size = 512; @@ -1245,6 +1264,10 @@ amqp_frame_codec_destroy(connection->amqp_frame_codec); frame_codec_destroy(connection->frame_codec); tickcounter_destroy(connection->tick_counter); + if (connection->properties != NULL) + { + amqpvalue_destroy(connection->properties); + } free(connection->host_name); free(connection->container_id); @@ -1542,6 +1565,116 @@ return result; } +int connection_set_properties(CONNECTION_HANDLE connection, fields properties) +{ + int result; + + /* Codes_SRS_CONNECTION_01_261: [If connection is NULL, connection_set_properties shall fail and return a non-zero value.] */ + if (connection == NULL) + { + LogError("NULL connection"); + result = __FAILURE__; + } + 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.] */ + if (connection->connection_state != CONNECTION_STATE_START) + { + LogError("Connection already open"); + result = __FAILURE__; + } + else + { + if (properties == NULL) + { + /* Codes_SRS_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. ]*/ + 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`. ]*/ + 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. ]*/ + LogError("Cannot clone connection properties"); + result = __FAILURE__; + } + else + { + /* Codes_SRS_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) + { + fields_destroy(connection->properties); + } + + connection->properties = new_properties; + + /* Codes_SRS_CONNECTION_01_264: [ On success it shall return 0. ]*/ + result = 0; + } + } + } + } + + return result; +} + +int connection_get_properties(CONNECTION_HANDLE connection, fields* properties) +{ + int result; + + /* Codes_SRS_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)) + { + LogError("Bad arguments: connection = %p, properties = %p", + connection, properties); + result = __FAILURE__; + } + else + { + if (connection->properties == NULL) + { + /* Codes_SRS_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.] */ + 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`. ]*/ + *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. ]*/ + LogError("Cannot clone properties"); + result = __FAILURE__; + } + else + { + /* Codes_SRS_CONNECTION_01_271: [On success, connection_get_properties shall return 0.] */ + result = 0; + } + } + } + + return result; +} + int connection_get_remote_max_frame_size(CONNECTION_HANDLE connection, uint32_t* remote_max_frame_size) { int result;