static int send_open_frame()

in src/connection.c [280:450]


static int send_open_frame(CONNECTION_HANDLE connection)
{
    int result;

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

        connection_set_state(connection, CONNECTION_STATE_END);
        result = MU_FAILURE;
    }
    else
    {
        /* 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_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");
            }

            connection_set_state(connection, CONNECTION_STATE_END);
            result = MU_FAILURE;
        }
        else
        {
            /* 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_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");
                }

                connection_set_state(connection, CONNECTION_STATE_END);
                result = MU_FAILURE;
            }
            /* 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_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");
                }

                connection_set_state(connection, CONNECTION_STATE_END);
                result = MU_FAILURE;
            }
            /* 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_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_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");
                }

                connection_set_state(connection, CONNECTION_STATE_END);
                result = MU_FAILURE;
            }
            /* 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_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_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");
                }

                connection_set_state(connection, CONNECTION_STATE_END);
                result = MU_FAILURE;
            }
            /* 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_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_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");
                }

                connection_set_state(connection, CONNECTION_STATE_END);
                result = MU_FAILURE;
            }
            else
            {
                AMQP_VALUE open_performative_value = amqpvalue_create_open(open_performative);
                if (open_performative_value == NULL)
                {
                    LogError("Cannot create OPEN AMQP value");

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

                    connection_set_state(connection, CONNECTION_STATE_END);
                    result = MU_FAILURE;
                }
                else
                {
                    /* 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_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");
                        }

                        connection_set_state(connection, CONNECTION_STATE_END);
                        result = MU_FAILURE;
                    }
                    else
                    {
                        if (connection->is_trace_on == 1)
                        {
                            log_outgoing_frame(open_performative_value);
                        }

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

                    amqpvalue_destroy(open_performative_value);
                }
            }

            open_destroy(open_performative);
        }
    }

    return result;
}