A small memory footprint AMQP implimentation
Dependents: iothub_client_sample_amqp remote_monitoring simplesample_amqp
Diff: connection.c
- Revision:
- 1:eab586236bfe
- Parent:
- 0:6ae2f7bca550
- Child:
- 4:98007eb79fa8
diff -r 6ae2f7bca550 -r eab586236bfe connection.c --- a/connection.c Fri Apr 08 12:01:10 2016 -0700 +++ b/connection.c Sun Apr 24 16:40:31 2016 -0700 @@ -606,7 +606,7 @@ if (connection_instance->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.] */ - connection_set_state(connection_instance, CONNECTION_STATE_END); + connection_set_state(connection_instance, CONNECTION_STATE_ERROR); (void)xio_close(connection_instance->io, NULL, NULL); } } @@ -1340,48 +1340,86 @@ return result; } +uint64_t connection_handle_deadlines(CONNECTION_HANDLE connection) +{ + uint64_t local_deadline = (uint64_t )-1; + uint64_t remote_deadline = (uint64_t)-1; + + if (connection != NULL) + { + uint64_t current_ms; + + if (tickcounter_get_current_ms(connection->tick_counter, ¤t_ms) != 0) + { + close_connection_with_error(connection, "amqp:internal-error", "Could not get tick count"); + } + else + { + if (connection->idle_timeout_specified && (connection->idle_timeout != 0)) + { + /* Calculate time until configured idle timeout expires */ + + uint64_t time_since_last_received = current_ms - connection->last_frame_received_time; + if (time_since_last_received < connection->idle_timeout) + { + local_deadline = connection->idle_timeout - time_since_last_received; + } + else + { + local_deadline = 0; + + /* close connection */ + close_connection_with_error(connection, "amqp:internal-error", "No frame received for the idle timeout"); + } + } + + if (local_deadline != 0 && connection->remote_idle_timeout != 0) + { + /* Calculate time until remote idle timeout expires */ + + uint64_t remote_idle_timeout = (connection->remote_idle_timeout / 2); + uint64_t time_since_last_sent = current_ms - connection->last_frame_sent_time; + + if (time_since_last_sent < remote_idle_timeout) + { + remote_deadline = remote_idle_timeout - time_since_last_sent; + } + else + { + connection->on_send_complete = NULL; + if (amqp_frame_codec_encode_empty_frame(connection->amqp_frame_codec, 0, on_bytes_encoded, connection) != 0) + { + /* close connection */ + close_connection_with_error(connection, "amqp:internal-error", "Cannot send empty frame"); + } + else + { + LOG(connection->logger, LOG_LINE, "-> Empty frame"); + + connection->last_frame_sent_time = current_ms; + + remote_deadline = remote_idle_timeout; + } + } + } + } + } + + /* Return the shorter of each deadline, or 0 to indicate connection closed */ + return local_deadline > remote_deadline ? remote_deadline : local_deadline; +} + void connection_dowork(CONNECTION_HANDLE connection) { /* Codes_SRS_CONNECTION_01_078: [If handle is NULL, connection_dowork shall do nothing.] */ - if (connection != NULL) - { - uint64_t current_ms; - - if (tickcounter_get_current_ms(connection->tick_counter, ¤t_ms) != 0) - { - close_connection_with_error(connection, "amqp:internal-error", "Could not get tick count"); - } - else - { - if (connection->idle_timeout_specified && - (connection->idle_timeout != 0) && - (current_ms - connection->last_frame_received_time > connection->idle_timeout)) - { - /* close connection */ - close_connection_with_error(connection, "amqp:internal-error", "No frame received for the idle timeout"); - } - - if ((connection->remote_idle_timeout != 0) && - (current_ms - connection->last_frame_sent_time > connection->remote_idle_timeout / 2)) - { - connection->on_send_complete = NULL; - if (amqp_frame_codec_encode_empty_frame(connection->amqp_frame_codec, 0, on_bytes_encoded, connection) != 0) - { - /* close connection */ - close_connection_with_error(connection, "amqp:internal-error", "Cannot send empty frame"); - } - else - { - LOG(connection->logger, LOG_LINE, "-> Empty frame"); - - connection->last_frame_sent_time = current_ms; - } - } - } - - /* Codes_SRS_CONNECTION_01_076: [connection_dowork shall schedule the underlying IO interface to do its work by calling xio_dowork.] */ - xio_dowork(connection->io); - } + if (connection != NULL) + { + 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.] */ + xio_dowork(connection->io); + } + } } ENDPOINT_HANDLE connection_create_endpoint(CONNECTION_HANDLE connection)