CONNECTION_HANDLE connection_create2()

in src/connection.c [1134:1297]


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;

    if ((xio == NULL) ||
        (container_id == 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;
    }
    else
    {
        connection = (CONNECTION_HANDLE)calloc(1, sizeof(CONNECTION_INSTANCE));
        /* 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");
        }
        else
        {
            connection->io = xio;

            /* 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_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;
            }
            else
            {
                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_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);
                    connection = NULL;
                }
                else
                {
                    if (hostname != NULL)
                    {
                        size_t hostname_length = strlen(hostname);
                        connection->host_name = (char*)malloc(hostname_length + 1);
                        if (connection->host_name == 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);
                            free(connection);
                            connection = NULL;
                        }
                        else
                        {
                            (void)memcpy(connection->host_name, hostname, hostname_length + 1);
                        }
                    }
                    else
                    {
                        connection->host_name = NULL;
                    }

                    if (connection != NULL)
                    {
                        size_t container_id_length = strlen(container_id);
                        connection->container_id = (char*)malloc(container_id_length + 1);
                        if (connection->container_id == 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);
                            frame_codec_destroy(connection->frame_codec);
                            free(connection);
                            connection = NULL;
                        }
                        else
                        {
                            connection->tick_counter = tickcounter_create();
                            if (connection->tick_counter == NULL)
                            {
                                LogError("Cannot create tick counter");
                                free(connection->container_id);
                                free(connection->host_name);
                                amqp_frame_codec_destroy(connection->amqp_frame_codec);
                                frame_codec_destroy(connection->frame_codec);
                                free(connection);
                                connection = NULL;
                            }
                            else
                            {
                                (void)memcpy(connection->container_id, container_id, container_id_length + 1);

                                /* 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_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;
                                connection->idle_timeout_empty_frame_send_ratio = 0.5;

                                connection->endpoint_count = 0;
                                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;
                                connection->is_trace_on = 0;

                                /* Mark that settings have not yet been set by the user */
                                connection->idle_timeout_specified = 0;

                                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;
                                connection->on_connection_state_changed_callback_context = on_connection_state_changed_context;

                                if (tickcounter_get_current_ms(connection->tick_counter, &connection->last_frame_received_time) != 0)
                                {
                                    LogError("Could not retrieve time for last frame received time");
                                    tickcounter_destroy(connection->tick_counter);
                                    free(connection->container_id);
                                    free(connection->host_name);
                                    amqp_frame_codec_destroy(connection->amqp_frame_codec);
                                    frame_codec_destroy(connection->frame_codec);
                                    free(connection);
                                    connection = NULL;
                                }
                                else
                                {
                                    connection->last_frame_sent_time = connection->last_frame_received_time;

                                    /* 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);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    return connection;
}