static void s_on_stream_complete_fn()

in source/credentials_provider_sts.c [303:426]


static void s_on_stream_complete_fn(struct aws_http_stream *stream, int error_code, void *user_data) {
    int http_response_code = 0;
    struct sts_creds_provider_user_data *provider_user_data = user_data;
    struct aws_credentials_provider_sts_impl *provider_impl = provider_user_data->provider->impl;
    struct aws_xml_parser *xml_parser = NULL;

    provider_user_data->error_code = error_code;

    if (provider_impl->function_table->aws_http_stream_get_incoming_response_status(stream, &http_response_code)) {
        goto finish;
    }

    if (http_response_code != 200) {
        provider_user_data->error_code = AWS_AUTH_CREDENTIALS_PROVIDER_HTTP_STATUS_FAILURE;
    }

    provider_impl->function_table->aws_http_stream_release(stream);

    AWS_LOGF_DEBUG(
        AWS_LS_AUTH_CREDENTIALS_PROVIDER,
        "(id=%p): AssumeRole call completed with http status %d",
        (void *)provider_user_data->provider,
        http_response_code);

    if (error_code || http_response_code != AWS_HTTP_STATUS_CODE_200_OK) {
        /* prevent connection reuse. */
        provider_impl->function_table->aws_http_connection_close(provider_user_data->connection);

        enum aws_retry_error_type error_type = http_response_code >= 400 && http_response_code < 500
                                                   ? AWS_RETRY_ERROR_TYPE_CLIENT_ERROR
                                                   : AWS_RETRY_ERROR_TYPE_SERVER_ERROR;

        if (s_is_transient_error(error_code)) {
            error_type = AWS_RETRY_ERROR_TYPE_TRANSIENT;
        }

        /* server throttling us is retryable */
        if (http_response_code == AWS_HTTP_STATUS_CODE_429_TOO_MANY_REQUESTS) {
            /* force a new connection on this. */
            error_type = AWS_RETRY_ERROR_TYPE_THROTTLING;
        }

        s_reset_request_specific_data(provider_user_data);

        /* don't retry client errors at all. */
        if (error_type != AWS_RETRY_ERROR_TYPE_CLIENT_ERROR) {
            if (aws_retry_strategy_schedule_retry(
                    provider_user_data->retry_token, error_type, s_on_retry_ready, provider_user_data)) {
                AWS_LOGF_ERROR(
                    AWS_LS_AUTH_CREDENTIALS_PROVIDER,
                    "(id=%p): failed to schedule retry: %s",
                    (void *)provider_user_data->provider,
                    aws_error_str(aws_last_error()));
                goto finish;
            }
            return;
        }
    }

    if (!error_code && http_response_code == AWS_HTTP_STATUS_CODE_200_OK) {
        /* update the book keeping so we can let the retry strategy make determinations about when the service is
         * healthy after an outage. */
        if (aws_retry_token_record_success(provider_user_data->retry_token)) {
            AWS_LOGF_ERROR(
                AWS_LS_AUTH_CREDENTIALS_PROVIDER,
                "(id=%p): failed to register operation success: %s",
                (void *)provider_user_data->provider,
                aws_error_str(aws_last_error()));
            goto finish;
        }

        struct aws_xml_parser_options options;
        AWS_ZERO_STRUCT(options);
        options.doc = aws_byte_cursor_from_buf(&provider_user_data->output_buf);

        xml_parser = aws_xml_parser_new(provider_user_data->provider->allocator, &options);

        if (xml_parser == NULL) {
            goto finish;
        }

        uint64_t now = UINT64_MAX;
        if (provider_impl->system_clock_fn(&now) != AWS_OP_SUCCESS) {
            goto finish;
        }

        uint64_t now_seconds = aws_timestamp_convert(now, AWS_TIMESTAMP_NANOS, AWS_TIMESTAMP_SECS, NULL);

        if (aws_xml_parser_parse(xml_parser, s_on_node_encountered_fn, provider_user_data)) {
            provider_user_data->error_code = aws_last_error();
            AWS_LOGF_ERROR(
                AWS_LS_AUTH_CREDENTIALS_PROVIDER,
                "(id=%p): credentials parsing failed with error %s",
                (void *)provider_user_data->credentials,
                aws_error_debug_str(provider_user_data->error_code));
            goto finish;
        }

        if (provider_user_data->access_key_id && provider_user_data->secret_access_key &&
            provider_user_data->session_token) {

            provider_user_data->credentials = aws_credentials_new_from_string(
                provider_user_data->allocator,
                provider_user_data->access_key_id,
                provider_user_data->secret_access_key,
                provider_user_data->session_token,
                now_seconds + provider_impl->duration_seconds);
        } else {
            AWS_LOGF_ERROR(
                AWS_LS_AUTH_CREDENTIALS_PROVIDER,
                "(id=%p): credentials document was corrupted, treating as an error.",
                (void *)provider_user_data->provider);
        }
    }

finish:

    if (xml_parser != NULL) {
        aws_xml_parser_destroy(xml_parser);
        xml_parser = NULL;
    }

    s_clean_up_user_data(provider_user_data);
}