private async Task <Response> SendInternalAsync(Request request, HttpWebRequestState state, CancellationToken cancellationToken)
        {
            using (cancellationToken.Register(state.CancelRequest))
            {
                for (state.ConnectionAttempt = 1; state.ConnectionAttempt <= ConnectionAttempts; state.ConnectionAttempt++)
                {
                    using (state)
                    {
                        if (state.RequestCancelled)
                        {
                            return(new Response(ResponseCode.Canceled));
                        }

                        state.Reset();
                        state.Request = HttpWebRequestFactory.Create(request, state.TimeRemaining);

                        HttpActionStatus status;

                        // (iloktionov): Шаг 1 - отправить тело запроса, если оно имеется.
                        if (state.RequestCancelled)
                        {
                            return(new Response(ResponseCode.Canceled));
                        }

                        if (request.Content != null)
                        {
                            status = await connectTimeLimiter.LimitConnectTime(SendRequestBodyAsync(request, state), request, state, ConnectionTimeout).ConfigureAwait(false);

                            if (status == HttpActionStatus.ConnectionFailure)
                            {
                                continue;
                            }

                            if (status != HttpActionStatus.Success)
                            {
                                return(ResponseFactory.BuildFailureResponse(status, state));
                            }
                        }

                        // (iloktionov): Шаг 2 - получить ответ от сервера.
                        if (state.RequestCancelled)
                        {
                            return(new Response(ResponseCode.Canceled));
                        }

                        status = request.Content != null
                            ? await GetResponseAsync(request, state).ConfigureAwait(false)
                            : await connectTimeLimiter.LimitConnectTime(GetResponseAsync(request, state), request, state, ConnectionTimeout).ConfigureAwait(false);

                        if (status == HttpActionStatus.ConnectionFailure)
                        {
                            continue;
                        }

                        if (status != HttpActionStatus.Success)
                        {
                            return(ResponseFactory.BuildFailureResponse(status, state));
                        }

                        // (iloktionov): Шаг 3 - скачать тело ответа, если оно имеется.
                        if (!NeedToReadResponseBody(request, state))
                        {
                            return(ResponseFactory.BuildSuccessResponse(state));
                        }

                        if (state.RequestCancelled)
                        {
                            return(new Response(ResponseCode.Canceled));
                        }

                        status = await ReadResponseBodyAsync(request, state).ConfigureAwait(false);

                        return(status == HttpActionStatus.Success
                            ? ResponseFactory.BuildSuccessResponse(state)
                            : ResponseFactory.BuildFailureResponse(status, state));
                    }
                }

                return(new Response(ResponseCode.ConnectFailure));
            }
        }