private async ValueTask ProcessInternal(HttpMessage message, bool async)
        {
            var request = CreateRequest(message.Request);

            ServicePointHelpers.SetLimits(request.ServicePoint);

            using var registration = message.CancellationToken.Register(state => ((HttpWebRequest)state).Abort(), request);
            try
            {
                if (message.Request.Content != null)
                {
                    using var requestStream = async ? await request.GetRequestStreamAsync().ConfigureAwait(false) : request.GetRequestStream();

                    if (async)
                    {
                        await message.Request.Content.WriteToAsync(requestStream, message.CancellationToken).ConfigureAwait(false);
                    }
                    else
                    {
                        message.Request.Content.WriteTo(requestStream, message.CancellationToken);
                    }
                }
                else
                {
                    // match the behavior of HttpClient
                    if (message.Request.Method != RequestMethod.Head &&
                        message.Request.Method != RequestMethod.Get &&
                        message.Request.Method != RequestMethod.Delete)
                    {
                        request.ContentLength = 0;
                    }

                    request.ContentType = null;
                }

                WebResponse webResponse;
                try
                {
                    webResponse = async ? await request.GetResponseAsync().ConfigureAwait(false) : request.GetResponse();
                }
                // HttpWebRequest throws for error responses catch that
                catch (WebException exception) when(exception.Response != null)
                {
                    webResponse = exception.Response;
                }

                message.Response = new HttpWebResponseImplementation(message.Request.ClientRequestId, (HttpWebResponse)webResponse);
            }
            // ObjectDisposedException might be thrown if the request is aborted during the content upload via SSL
            catch (ObjectDisposedException) when(message.CancellationToken.IsCancellationRequested)
            {
                CancellationHelper.ThrowIfCancellationRequested(message.CancellationToken);
            }
            catch (WebException webException)
            {
                // WebException is thrown in the case of .Abort() call
                CancellationHelper.ThrowIfCancellationRequested(message.CancellationToken);
                throw new RequestFailedException(0, webException.Message, webException);
            }
        }
            private async Task RetryAsync(Exception exception, bool async, CancellationToken cancellationToken)
            {
                // Depending on the timing, the stream can be closed as a result of cancellation when the transport closes the stream.
                // If the user requested cancellation, we translate to TaskCanceledException, similar to what we do HttpWebRequestTransport.
                if (exception is ObjectDisposedException)
                {
                    CancellationHelper.ThrowIfCancellationRequested(cancellationToken);
                }

                bool isNonCustomerCancelledException = exception is OperationCanceledException &&
                                                       !cancellationToken.IsCancellationRequested;

                if (!_responseClassifier.IsRetriableException(exception) && !isNonCustomerCancelledException)
                {
                    ExceptionDispatchInfo.Capture(exception).Throw();
                }

                if (_exceptions == null)
                {
                    _exceptions = new List <Exception>();
                }

                _exceptions.Add(exception);

                _retryCount++;

                if (_retryCount > _maxRetries)
                {
                    throw new AggregateException($"Retry failed after {_retryCount} tries", _exceptions);
                }

                _currentStream.Dispose();

                _currentStream = EnsureStream(async ? (await _asyncStreamFactory(_position).ConfigureAwait(false)) : _streamFactory(_position));
            }
        /// <summary>Throws a cancellation exception if cancellation has been requested via <paramref name="originalToken"/> or <paramref name="timeoutToken"/>.</summary>
        /// <param name="originalToken">The customer provided token.</param>
        /// <param name="timeoutToken">The linked token that is cancelled on timeout provided token.</param>
        /// <param name="inner">The inner exception to use.</param>
        /// <param name="timeout">The timeout used for the operation.</param>
#pragma warning disable CA1068 // Cancellation token has to be the last parameter
        internal static void ThrowIfCancellationRequestedOrTimeout(CancellationToken originalToken, CancellationToken timeoutToken, Exception?inner, TimeSpan timeout)
#pragma warning restore CA1068
        {
            CancellationHelper.ThrowIfCancellationRequested(originalToken);

            if (timeoutToken.IsCancellationRequested)
            {
                throw CancellationHelper.CreateOperationCanceledException(
                          inner,
                          timeoutToken,
                          $"The operation was cancelled because it exceeded the configured timeout of {timeout:g}. " +
                          $"Network timeout can be adjusted in {nameof(ClientOptions)}.{nameof(ClientOptions.Retry)}.{nameof(RetryOptions.NetworkTimeout)}.");
            }
        }