Ejemplo n.º 1
0
            public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
            {
                ValidateCopyToArgs(this, destination, bufferSize);

                if (cancellationToken.IsCancellationRequested)
                {
                    return(Task.FromCanceled(cancellationToken));
                }

                HttpConnection?connection = _connection;

                if (connection == null)
                {
                    // null if response body fully consumed
                    return(Task.CompletedTask);
                }

                Task copyTask = connection.CopyToUntilEofAsync(destination, bufferSize, cancellationToken);

                if (copyTask.IsCompletedSuccessfully)
                {
                    Finish(connection);
                    return(Task.CompletedTask);
                }

                return(CompleteCopyToAsync(copyTask, connection, cancellationToken));
            }
Ejemplo n.º 2
0
            public override int Read(Span <byte> buffer)
            {
                HttpConnection?connection = _connection;

                if (connection == null || buffer.Length == 0)
                {
                    // Response body fully consumed or the caller didn't ask for any data
                    return(0);
                }

                int bytesRead = connection.ReadBuffered(buffer);

                if (bytesRead == 0)
                {
                    // We cannot reuse this connection, so close it.
                    if (HttpTelemetry.IsEnabled)
                    {
                        LogRequestStop();
                    }
                    _connection = null;
                    connection.Dispose();
                }

                return(bytesRead);
            }
            private async Task DrainOnDisposeAsync()
            {
                HttpConnection?connection = _connection;         // Will be null after drain succeeds

                Debug.Assert(connection != null);
                try
                {
                    bool drained = await DrainAsync(connection._pool.Settings._maxResponseDrainSize).ConfigureAwait(false);

                    if (NetEventSource.Log.IsEnabled())
                    {
                        connection.Trace(drained ?
                                         "Connection drain succeeded" :
                                         $"Connection drain failed because MaxResponseDrainSize of {connection._pool.Settings._maxResponseDrainSize} bytes was exceeded");
                    }
                }
                catch (Exception e)
                {
                    if (NetEventSource.Log.IsEnabled())
                    {
                        connection.Trace($"Connection drain failed due to exception: {e}");
                    }

                    // Eat any exceptions and just Dispose.
                }

                base.Dispose(true);
            }
Ejemplo n.º 4
0
            public override async ValueTask <int> ReadAsync(Memory <byte> buffer, CancellationToken cancellationToken)
            {
                CancellationHelper.ThrowIfCancellationRequested(cancellationToken);

                HttpConnection?connection = _connection;

                if (connection == null || buffer.Length == 0)
                {
                    // Response body fully consumed or the caller didn't ask for any data
                    return(0);
                }

                ValueTask <int> readTask = connection.ReadAsync(buffer);
                int             bytesRead;

                if (readTask.IsCompletedSuccessfully)
                {
                    bytesRead = readTask.Result;
                }
                else
                {
                    CancellationTokenRegistration ctr = connection.RegisterCancellation(cancellationToken);
                    try
                    {
                        bytesRead = await readTask.ConfigureAwait(false);
                    }
                    catch (Exception exc) when(CancellationHelper.ShouldWrapInOperationCanceledException(exc, cancellationToken))
                    {
                        throw CancellationHelper.CreateOperationCanceledException(exc, cancellationToken);
                    }
                    finally
                    {
                        ctr.Dispose();
                    }
                }

                if (bytesRead == 0)
                {
                    // If cancellation is requested and tears down the connection, it could cause the read
                    // to return 0, which would otherwise signal the end of the data, but that would lead
                    // the caller to think that it actually received all of the data, rather than it ending
                    // early due to cancellation.  So we prioritize cancellation in this race condition, and
                    // if we read 0 bytes and then find that cancellation has requested, we assume cancellation
                    // was the cause and throw.
                    CancellationHelper.ThrowIfCancellationRequested(cancellationToken);

                    // We cannot reuse this connection, so close it.
                    if (HttpTelemetry.IsEnabled)
                    {
                        LogRequestStop();
                    }
                    _connection = null;
                    connection.Dispose();
                }

                return(bytesRead);
            }
Ejemplo n.º 5
0
 public void Dispose()
 {
     lock (this)
     {
         if (_httpConnection != null)
         {
             _httpConnection.Dispose();
             _httpConnection = null;
         }
     }
 }
Ejemplo n.º 6
0
        protected HttpConnection GetConnectionOrThrow()
        {
            HttpConnection?c = _connection;

            // Disposal should only ever happen if the user-code that was handed this instance disposed of
            // it, which is misuse, or held onto it and tried to use it later after we've disposed of it,
            // which is also misuse.
            ObjectDisposedException.ThrowIf(c is null, this);

            return(c);
        }
Ejemplo n.º 7
0
            public override async ValueTask <int> ReadAsync(Memory <byte> buffer, CancellationToken cancellationToken)
            {
                CancellationHelper.ThrowIfCancellationRequested(cancellationToken);

                HttpConnection?connection = _connection;

                if (connection == null || buffer.Length == 0)
                {
                    // Response body fully consumed or the caller didn't ask for any data
                    return(0);
                }

                ValueTask <int> readTask = connection.ReadBufferedAsync(buffer);
                int             bytesRead;

                if (readTask.IsCompletedSuccessfully)
                {
                    bytesRead = readTask.Result;
                }
                else
                {
                    CancellationTokenRegistration ctr = connection.RegisterCancellation(cancellationToken);
                    try
                    {
                        bytesRead = await readTask.ConfigureAwait(false);
                    }
                    catch (Exception exc) when(CancellationHelper.ShouldWrapInOperationCanceledException(exc, cancellationToken))
                    {
                        throw CancellationHelper.CreateOperationCanceledException(exc, cancellationToken);
                    }
                    finally
                    {
                        ctr.Dispose();
                    }
                }

                if (bytesRead == 0)
                {
                    // A cancellation request may have caused the EOF.
                    CancellationHelper.ThrowIfCancellationRequested(cancellationToken);

                    // We cannot reuse this connection, so close it.
                    if (HttpTelemetry.IsEnabled)
                    {
                        LogRequestStop();
                    }
                    _connection = null;
                    connection.Dispose();
                }

                return(bytesRead);
            }
Ejemplo n.º 8
0
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_connection != null)
                {
                    _connection.Dispose();
                    _connection = null;
                }
            }

            base.Dispose(disposing);
        }
Ejemplo n.º 9
0
            public override void Write(ReadOnlySpan <byte> buffer)
            {
                HttpConnection?connection = _connection;

                if (connection == null)
                {
                    throw new IOException(SR.ObjectDisposed_StreamClosed);
                }

                if (buffer.Length != 0)
                {
                    connection.WriteWithoutBuffering(buffer);
                }
            }
Ejemplo n.º 10
0
            public override ValueTask WriteAsync(ReadOnlyMemory <byte> buffer, CancellationToken cancellationToken)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return(ValueTask.FromCanceled(cancellationToken));
                }

                HttpConnection?connection = _connection;

                if (connection == null)
                {
                    return(ValueTask.FromException(ExceptionDispatchInfo.SetCurrentStackTrace(new IOException(SR.ObjectDisposed_StreamClosed))));
                }

                if (buffer.Length == 0)
                {
                    return(default);
Ejemplo n.º 11
0
            public override int Read(Span <byte> buffer)
            {
                HttpConnection?connection = _connection;

                if (connection == null)
                {
                    // Response body fully consumed or the caller didn't ask for any data
                    return(0);
                }

                int bytesRead = connection.ReadBuffered(buffer);

                if (bytesRead == 0 && buffer.Length != 0)
                {
                    // We cannot reuse this connection, so close it.
                    _connection = null;
                    connection.Dispose();
                }

                return(bytesRead);
            }
Ejemplo n.º 12
0
            public sealed override Task FlushAsync(CancellationToken ignored)
            {
                HttpConnection?connection = _connection;

                return(connection != null?
                       connection.FlushAsync().AsTask() :
Ejemplo n.º 13
0
        private int _requestStopCalled; // 0==no, 1==yes

        public HttpContentStream(HttpConnection connection)
        {
            _connection = connection;
        }
Ejemplo n.º 14
0
    public async Task <HttpResponseMessage> ExecuteRequestAsync(ODataRequest request, CancellationToken cancellationToken)
    {
        HttpConnection?httpConnection = null;

        try
        {
            await PreExecuteAsync(request).ConfigureAwait(false);

            _session.Trace("{0} request: {1}", request.Method, request.RequestMessage.RequestUri.AbsoluteUri);
            if (request.RequestMessage.Content != null && (_session.Settings.TraceFilter & ODataTrace.RequestContent) != 0)
            {
                var content = await request.RequestMessage.Content.ReadAsStringAsync().ConfigureAwait(false);

                _session.Trace("Request content:{0}{1}", Environment.NewLine, content);
            }

            HttpResponseMessage response;
            if (_session.Settings.RequestExecutor != null)
            {
                response = await _session.Settings.RequestExecutor(request.RequestMessage).ConfigureAwait(false);
            }
            else
            {
                httpConnection = _session.Settings.RenewHttpConnection
                                        ? new HttpConnection(_session.Settings)
                                        : _session.GetHttpConnection();

                response = await httpConnection.HttpClient.SendAsync(request.RequestMessage, cancellationToken).ConfigureAwait(false);

                if (cancellationToken.IsCancellationRequested)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                }
            }

            _session.Trace("Request completed: {0}", response.StatusCode);
            if (response.Content != null && (_session.Settings.TraceFilter & ODataTrace.ResponseContent) != 0)
            {
                var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

                _session.Trace("Response content:{0}{1}", Environment.NewLine, content);
            }

            await PostExecute(response).ConfigureAwait(false);

            return(response);
        }
        catch (WebException ex)
        {
            throw WebRequestException.CreateFromWebException(ex);
        }
        catch (AggregateException ex)
        {
            if (ex.InnerException is WebException)
            {
                throw WebRequestException.CreateFromWebException(ex.InnerException as WebException);
            }
            else
            {
                throw;
            }
        }
        finally
        {
            if (httpConnection != null && _session.Settings.RenewHttpConnection)
            {
                httpConnection.Dispose();
            }
        }
    }