Harden framing epilog

* Connection no longer needes Frame's processing Task
* Any exceptions from unusual processing is logged
This commit is contained in:
Louis DeJardin 2015-09-17 18:53:35 -07:00
parent 28250d9981
commit 30ec2cb0b1
2 changed files with 72 additions and 54 deletions

View File

@ -40,7 +40,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
SocketInput = new SocketInput(Memory2); SocketInput = new SocketInput(Memory2);
SocketOutput = new SocketOutput(Thread, _socket, _connectionId, Log); SocketOutput = new SocketOutput(Thread, _socket, _connectionId, Log);
_frame = new Frame(this); _frame = new Frame(this);
_frameTask = Task.Run(_frame.ProcessFraming); Task.Run(_frame.ProcessFraming);
_socket.ReadStart(_allocCallback, _readCallback, this); _socket.ReadStart(_allocCallback, _readCallback, this);
} }

View File

@ -9,6 +9,7 @@ using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Server.Kestrel.Infrastructure; using Microsoft.AspNet.Server.Kestrel.Infrastructure;
using Microsoft.Framework.Logging;
using Microsoft.Framework.Primitives; using Microsoft.Framework.Primitives;
// ReSharper disable AccessToModifiedClosure // ReSharper disable AccessToModifiedClosure
@ -98,73 +99,90 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
_responseHeaders.HeaderDate = DateTime.UtcNow.ToString("r"); _responseHeaders.HeaderDate = DateTime.UtcNow.ToString("r");
} }
public async Task ProcessFraming() public async void ProcessFraming()
{ {
var terminated = false; try
while (!terminated)
{ {
while (!terminated && !TakeStartLine(SocketInput)) var terminated = false;
while (!terminated)
{ {
terminated = SocketInput.RemoteIntakeFin; while (!terminated && !TakeStartLine(SocketInput))
if (!terminated)
{ {
await SocketInput; terminated = SocketInput.RemoteIntakeFin;
} if (!terminated)
}
while (!terminated && !TakeMessageHeaders(SocketInput))
{
terminated = SocketInput.RemoteIntakeFin;
if (!terminated)
{
await SocketInput;
}
}
if (!terminated)
{
MessageBody = MessageBody.For(HttpVersion, _requestHeaders, this);
_keepAlive = MessageBody.RequestKeepAlive;
RequestBody = new FrameRequestStream(MessageBody);
ResponseBody = new FrameResponseStream(this);
DuplexStream = new FrameDuplexStream(RequestBody, ResponseBody);
Exception error = null;
try
{
await Application.Invoke(this).ConfigureAwait(false);
// Trigger FireOnStarting if ProduceStart hasn't been called yet.
// We call it here, so it can go through our normal error handling
// and respond with a 500 if an OnStarting callback throws.
if (!_responseStarted)
{ {
FireOnStarting(); await SocketInput;
} }
} }
catch (Exception ex)
while (!terminated && !TakeMessageHeaders(SocketInput))
{ {
error = ex; terminated = SocketInput.RemoteIntakeFin;
} if (!terminated)
finally {
{ await SocketInput;
FireOnCompleted(); }
ProduceEnd(error);
} }
terminated = !_keepAlive; if (!terminated)
{
MessageBody = MessageBody.For(HttpVersion, _requestHeaders, this);
_keepAlive = MessageBody.RequestKeepAlive;
RequestBody = new FrameRequestStream(MessageBody);
ResponseBody = new FrameResponseStream(this);
DuplexStream = new FrameDuplexStream(RequestBody, ResponseBody);
Exception error = null;
try
{
await Application.Invoke(this).ConfigureAwait(false);
// Trigger FireOnStarting if ProduceStart hasn't been called yet.
// We call it here, so it can go through our normal error handling
// and respond with a 500 if an OnStarting callback throws.
if (!_responseStarted)
{
FireOnStarting();
}
}
catch (Exception ex)
{
error = ex;
}
finally
{
FireOnCompleted();
ProduceEnd(error);
}
terminated = !_keepAlive;
}
Reset();
} }
Reset();
} }
catch (Exception ex)
{
Log.LogVerbose("Connection processing ended abnormally", ex);
}
finally
{
try
{
// Inform client no more data will ever arrive
ConnectionControl.End(ProduceEndType.SocketShutdownSend);
// Connection Terminated! // Wait for client to either disconnect or send unexpected data
ConnectionControl.End(ProduceEndType.SocketShutdownSend); await SocketInput;
// Wait for client to disconnect, or to receive unexpected data // Dispose socket
await SocketInput; ConnectionControl.End(ProduceEndType.SocketDisconnect);
}
ConnectionControl.End(ProduceEndType.SocketDisconnect); catch(Exception ex)
{
Log.LogVerbose("Connection shutdown abnormally", ex);
}
}
} }
public void OnStarting(Func<object, Task> callback, object state) public void OnStarting(Func<object, Task> callback, object state)