Trim req/resp streams by a field each

This commit is contained in:
Ben Adams 2015-12-07 04:59:29 +00:00
parent 706ff04160
commit 59bfb9ba10
2 changed files with 60 additions and 72 deletions

View File

@ -11,8 +11,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
public class FrameRequestStream : Stream public class FrameRequestStream : Stream
{ {
private readonly MessageBody _body; private readonly MessageBody _body;
private bool _stopped; private StreamState _state;
private bool _aborted;
public FrameRequestStream(MessageBody body) public FrameRequestStream(MessageBody body)
{ {
@ -52,14 +51,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
public override int Read(byte[] buffer, int offset, int count) public override int Read(byte[] buffer, int offset, int count)
{ {
if (_stopped) ValidateState();
{
throw new ObjectDisposedException(nameof(FrameRequestStream));
}
if (_aborted)
{
throw new IOException("The request has been aborted.");
}
return ReadAsync(buffer, offset, count).GetAwaiter().GetResult(); return ReadAsync(buffer, offset, count).GetAwaiter().GetResult();
} }
@ -67,14 +59,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
#if NET451 #if NET451
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{ {
if (_stopped) ValidateState();
{
throw new ObjectDisposedException(nameof(FrameRequestStream));
}
if (_aborted)
{
throw new IOException("The request has been aborted.");
}
var task = ReadAsync(buffer, offset, count, CancellationToken.None, state); var task = ReadAsync(buffer, offset, count, CancellationToken.None, state);
if (callback != null) if (callback != null)
@ -91,14 +76,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
private Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken, object state) private Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken, object state)
{ {
if (_stopped) ValidateState();
{
throw new ObjectDisposedException(nameof(FrameRequestStream));
}
if (_aborted)
{
throw new IOException("The request has been aborted.");
}
var tcs = new TaskCompletionSource<int>(state); var tcs = new TaskCompletionSource<int>(state);
var task = _body.ReadAsync(new ArraySegment<byte>(buffer, offset, count), cancellationToken); var task = _body.ReadAsync(new ArraySegment<byte>(buffer, offset, count), cancellationToken);
@ -124,14 +102,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{ {
if (_stopped) ValidateState();
{
throw new ObjectDisposedException(nameof(FrameRequestStream));
}
if (_aborted)
{
throw new IOException("The request has been aborted.");
}
return _body.ReadAsync(new ArraySegment<byte>(buffer, offset, count), cancellationToken); return _body.ReadAsync(new ArraySegment<byte>(buffer, offset, count), cancellationToken);
} }
@ -145,14 +116,37 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
{ {
// Can't use dispose (or close) as can be disposed too early by user code // Can't use dispose (or close) as can be disposed too early by user code
// As exampled in EngineTests.ZeroContentLengthNotSetAutomaticallyForCertainStatusCodes // As exampled in EngineTests.ZeroContentLengthNotSetAutomaticallyForCertainStatusCodes
_stopped = true; _state = StreamState.Disposed;
} }
public void Abort() public void Abort()
{ {
// We don't want to throw an ODE until the app func actually completes. // We don't want to throw an ODE until the app func actually completes.
// If the request is aborted, we throw an IOException instead. // If the request is aborted, we throw an IOException instead.
_aborted = true; if (_state != StreamState.Disposed)
{
_state = StreamState.Aborted;
}
}
private void ValidateState()
{
switch (_state)
{
case StreamState.Open:
return;
case StreamState.Disposed:
throw new ObjectDisposedException(nameof(FrameRequestStream));
case StreamState.Aborted:
throw new IOException("The request has been aborted.");
}
}
private enum StreamState
{
Open,
Disposed,
Aborted
} }
} }
} }

View File

@ -11,8 +11,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
class FrameResponseStream : Stream class FrameResponseStream : Stream
{ {
private readonly FrameContext _context; private readonly FrameContext _context;
private bool _stopped; private StreamState _state;
private bool _aborted;
public FrameResponseStream(FrameContext context) public FrameResponseStream(FrameContext context)
{ {
@ -37,28 +36,14 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
public override void Flush() public override void Flush()
{ {
if (_stopped) ValidateState();
{
throw new ObjectDisposedException(nameof(FrameResponseStream));
}
if (_aborted)
{
throw new IOException("The request has been aborted.");
}
_context.FrameControl.Flush(); _context.FrameControl.Flush();
} }
public override Task FlushAsync(CancellationToken cancellationToken) public override Task FlushAsync(CancellationToken cancellationToken)
{ {
if (_stopped) ValidateState();
{
throw new ObjectDisposedException(nameof(FrameResponseStream));
}
if (_aborted)
{
throw new IOException("The request has been aborted.");
}
return _context.FrameControl.FlushAsync(cancellationToken); return _context.FrameControl.FlushAsync(cancellationToken);
} }
@ -80,28 +65,14 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
public override void Write(byte[] buffer, int offset, int count) public override void Write(byte[] buffer, int offset, int count)
{ {
if (_stopped) ValidateState();
{
throw new ObjectDisposedException(nameof(FrameResponseStream));
}
if (_aborted)
{
throw new IOException("The request has been aborted.");
}
_context.FrameControl.Write(new ArraySegment<byte>(buffer, offset, count)); _context.FrameControl.Write(new ArraySegment<byte>(buffer, offset, count));
} }
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{ {
if (_stopped) ValidateState();
{
throw new ObjectDisposedException(nameof(FrameResponseStream));
}
if (_aborted)
{
throw new IOException("The request has been aborted.");
}
return _context.FrameControl.WriteAsync(new ArraySegment<byte>(buffer, offset, count), cancellationToken); return _context.FrameControl.WriteAsync(new ArraySegment<byte>(buffer, offset, count), cancellationToken);
} }
@ -110,14 +81,37 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
{ {
// Can't use dispose (or close) as can be disposed too early by user code // Can't use dispose (or close) as can be disposed too early by user code
// As exampled in EngineTests.ZeroContentLengthNotSetAutomaticallyForCertainStatusCodes // As exampled in EngineTests.ZeroContentLengthNotSetAutomaticallyForCertainStatusCodes
_stopped = true; _state = StreamState.Disposed;
} }
public void Abort() public void Abort()
{ {
// We don't want to throw an ODE until the app func actually completes. // We don't want to throw an ODE until the app func actually completes.
// If the request is aborted, we throw an IOException instead. // If the request is aborted, we throw an IOException instead.
_aborted = true; if (_state != StreamState.Disposed)
{
_state = StreamState.Aborted;
}
}
private void ValidateState()
{
switch (_state)
{
case StreamState.Open:
return;
case StreamState.Disposed:
throw new ObjectDisposedException(nameof(FrameResponseStream));
case StreamState.Aborted:
throw new IOException("The request has been aborted.");
}
}
private enum StreamState
{
Open,
Disposed,
Aborted
} }
} }
} }