IOTHUB_CLIENT_RESULT IoTHubTransport_AMQP_Common_SetOption()

in iothub_client/src/iothubtransport_amqp_common.c [1824:2032]


IOTHUB_CLIENT_RESULT IoTHubTransport_AMQP_Common_SetOption(TRANSPORT_LL_HANDLE handle, const char* option, const void* value)
{
    IOTHUB_CLIENT_RESULT result;

    if ((handle == NULL) || (option == NULL) || (value == NULL))
    {
        LogError("Invalid parameter (NULL) passed to AMQP transport SetOption (handle=%p, options=%p, value=%p)", handle, option, value);
        result = IOTHUB_CLIENT_INVALID_ARG;
    }
    else
    {
        AMQP_TRANSPORT_INSTANCE* transport_instance = (AMQP_TRANSPORT_INSTANCE*)handle;
        bool is_device_specific_option;

        if (strcmp(OPTION_CBS_REQUEST_TIMEOUT, option) == 0)
        {
            is_device_specific_option = true;
            transport_instance->option_cbs_request_timeout_secs = *(size_t*)value;
        }
        else if (strcmp(OPTION_EVENT_SEND_TIMEOUT_SECS, option) == 0)
        {
            is_device_specific_option = true;
            transport_instance->option_send_event_timeout_secs = *(size_t*)value;
        }
        else
        {
            is_device_specific_option = false;
        }

        if (is_device_specific_option)
        {
            if (IoTHubTransport_AMQP_Common_Device_SetOption(handle, option, (void*)value) != RESULT_OK)
            {
                LogError("transport failed setting option '%s' (failed setting option on one or more registered devices)", option);
                result = IOTHUB_CLIENT_ERROR;
            }
            else
            {
                result = IOTHUB_CLIENT_OK;
            }
        }
        else if (strcmp(OPTION_RETRY_INTERVAL_SEC, option) == 0)
        {
            if (retry_control_set_option(transport_instance->connection_retry_control, RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS, value) != 0)
            {
                LogError("Failure setting retry interval option");
                result = IOTHUB_CLIENT_ERROR;
            }
            else
            {
                result = IOTHUB_CLIENT_OK;
            }
        }
        else if (strcmp(OPTION_RETRY_MAX_DELAY_SECS, option) == 0)
        {
            if (retry_control_set_option(transport_instance->connection_retry_control, RETRY_CONTROL_OPTION_MAX_DELAY_IN_SECS, value) != 0)
            {
                LogError("Failure setting retry max delay option");
                result = IOTHUB_CLIENT_ERROR;
            }
            else
            {
                result = IOTHUB_CLIENT_OK;
            }
        }
        else if ((strcmp(OPTION_SERVICE_SIDE_KEEP_ALIVE_FREQ_SECS, option) == 0) || (strcmp(OPTION_C2D_KEEP_ALIVE_FREQ_SECS, option) == 0))
        {
            transport_instance->svc2cl_keep_alive_timeout_secs = *(size_t*)value;
            result = IOTHUB_CLIENT_OK;
        }
        else if (strcmp(OPTION_REMOTE_IDLE_TIMEOUT_RATIO, option) == 0)
        {

            if ((*(double*)value <= 0.0) || (*(double*)value >= MAX_SERVICE_KEEP_ALIVE_RATIO))
            {
                LogError("Invalid remote idle ratio %lf", *(double*) value);
                result = IOTHUB_CLIENT_INVALID_ARG;
            }
            else
            {
                transport_instance->cl2svc_keep_alive_send_ratio = *(double*)value; // override the default and set the user configured remote idle ratio value
                result = IOTHUB_CLIENT_OK;
            }

        }
        else if (strcmp(OPTION_LOG_TRACE, option) == 0)
        {
            transport_instance->is_trace_on = *((bool*)value);

            if (transport_instance->amqp_connection != NULL &&
                amqp_connection_set_logging(transport_instance->amqp_connection, transport_instance->is_trace_on) != RESULT_OK)
            {
                LogError("transport failed setting option '%s' (amqp_connection_set_logging failed)", option);
                result = IOTHUB_CLIENT_ERROR;
            }
            else
            {
                result = IOTHUB_CLIENT_OK;
            }
        }
        else if (strcmp(OPTION_HTTP_PROXY, option) == 0)
        {
            HTTP_PROXY_OPTIONS* proxy_options = (HTTP_PROXY_OPTIONS*)value;

            if (transport_instance->tls_io != NULL)
            {
                LogError("Cannot set proxy option once the underlying IO is created");
                result = IOTHUB_CLIENT_ERROR;
            }
            else if (proxy_options->host_address == NULL)
            {
                LogError("NULL host_address in proxy options");
                result = IOTHUB_CLIENT_INVALID_ARG;
            }
            else if (((proxy_options->username == NULL) || (proxy_options->password == NULL)) &&
                (proxy_options->username != proxy_options->password))
            {
                LogError("Only one of username and password for proxy settings was NULL");
                result = IOTHUB_CLIENT_INVALID_ARG;
            }
            else
            {
                char* copied_proxy_hostname = NULL;
                char* copied_proxy_username = NULL;
                char* copied_proxy_password = NULL;

                transport_instance->http_proxy_port = proxy_options->port;
                if (mallocAndStrcpy_s(&copied_proxy_hostname, proxy_options->host_address) != 0)
                {
                    LogError("Cannot copy HTTP proxy hostname");
                    result = IOTHUB_CLIENT_ERROR;
                }
                else if ((proxy_options->username != NULL) && (mallocAndStrcpy_s(&copied_proxy_username, proxy_options->username) != 0))
                {
                    free(copied_proxy_hostname);
                    LogError("Cannot copy HTTP proxy username");
                    result = IOTHUB_CLIENT_ERROR;
                }
                else if ((proxy_options->password != NULL) && (mallocAndStrcpy_s(&copied_proxy_password, proxy_options->password) != 0))
                {
                    if (copied_proxy_username != NULL)
                    {
                        free(copied_proxy_username);
                    }
                    free(copied_proxy_hostname);
                    LogError("Cannot copy HTTP proxy password");
                    result = IOTHUB_CLIENT_ERROR;
                }
                else
                {
                    free_proxy_data(transport_instance);

                    transport_instance->http_proxy_hostname = copied_proxy_hostname;
                    transport_instance->http_proxy_username = copied_proxy_username;
                    transport_instance->http_proxy_password = copied_proxy_password;

                    result = IOTHUB_CLIENT_OK;
                }
            }
        }
        else
        {
            result = IOTHUB_CLIENT_OK;

            if (strcmp(OPTION_X509_CERT, option) == 0 || strcmp(OPTION_X509_PRIVATE_KEY, option) == 0)
            {
                if (transport_instance->preferred_authentication_mode == AMQP_TRANSPORT_AUTHENTICATION_MODE_NOT_SET)
                {
                    transport_instance->preferred_authentication_mode = AMQP_TRANSPORT_AUTHENTICATION_MODE_X509;
                }
                else if (transport_instance->preferred_authentication_mode != AMQP_TRANSPORT_AUTHENTICATION_MODE_X509)
                {
                    LogError("transport failed setting option '%s' (preferred authentication method is not x509)", option);
                    result = IOTHUB_CLIENT_INVALID_ARG;
                }
                else
                {
                    IoTHubClient_Auth_Set_x509_Type(transport_instance->authorization_module, true);
                }
            }

            if (result != IOTHUB_CLIENT_INVALID_ARG)
            {
                if (transport_instance->tls_io == NULL &&
                    get_new_underlying_io_transport(transport_instance, &transport_instance->tls_io) != RESULT_OK)
                {
                    LogError("transport failed setting option '%s' (failed to obtain a TLS I/O transport).", option);
                    result = IOTHUB_CLIENT_ERROR;
                }
                else if (xio_setoption(transport_instance->tls_io, option, value) != RESULT_OK)
                {
                    LogError("transport failed setting option '%s' (xio_setoption failed)", option);
                    result = IOTHUB_CLIENT_ERROR;
                }
                else
                {
                    if (save_underlying_io_transport_options(transport_instance) != RESULT_OK)
                    {
                        LogError("IoTHubTransport_AMQP_Common_SetOption failed to save underlying I/O options; failure will be ignored");
                    }

                    result = IOTHUB_CLIENT_OK;
                }
            }
        }
    }

    return result;
}