Properly close keep alive connections
This commit is contained in:
parent
43ebf710ab
commit
b162202519
|
|
@ -9,6 +9,9 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
{
|
{
|
||||||
public class Connection : ConnectionContext, IConnectionControl
|
public class Connection : ConnectionContext, IConnectionControl
|
||||||
{
|
{
|
||||||
|
private const int EOF = -4095;
|
||||||
|
private const int ECONNRESET = -4077;
|
||||||
|
|
||||||
private static readonly Action<UvStreamHandle, int, Exception, object> _readCallback = ReadCallback;
|
private static readonly Action<UvStreamHandle, int, Exception, object> _readCallback = ReadCallback;
|
||||||
private static readonly Func<UvStreamHandle, int, object, Libuv.uv_buf_t> _allocCallback = AllocCallback;
|
private static readonly Func<UvStreamHandle, int, object, Libuv.uv_buf_t> _allocCallback = AllocCallback;
|
||||||
|
|
||||||
|
|
@ -54,7 +57,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
SocketInput.Unpin(status);
|
SocketInput.Unpin(status);
|
||||||
|
|
||||||
var normalRead = error == null && status > 0;
|
var normalRead = error == null && status > 0;
|
||||||
var normalDone = status == 0 || status == -4077 || status == -4095;
|
var normalDone = status == 0 || status == ECONNRESET || status == EOF;
|
||||||
var errorDone = !(normalDone || normalRead);
|
var errorDone = !(normalDone || normalRead);
|
||||||
|
|
||||||
if (normalRead)
|
if (normalRead)
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
if (input.Buffer.Count == 0 && input.RemoteIntakeFin)
|
if (input.Buffer.Count == 0 && input.RemoteIntakeFin)
|
||||||
{
|
{
|
||||||
_mode = Mode.Terminated;
|
_mode = Mode.Terminated;
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TakeStartLine(input))
|
if (!TakeStartLine(input))
|
||||||
|
|
@ -102,6 +102,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
if (input.RemoteIntakeFin)
|
if (input.RemoteIntakeFin)
|
||||||
{
|
{
|
||||||
_mode = Mode.Terminated;
|
_mode = Mode.Terminated;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -113,7 +114,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
if (input.Buffer.Count == 0 && input.RemoteIntakeFin)
|
if (input.Buffer.Count == 0 && input.RemoteIntakeFin)
|
||||||
{
|
{
|
||||||
_mode = Mode.Terminated;
|
_mode = Mode.Terminated;
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var endOfHeaders = false;
|
var endOfHeaders = false;
|
||||||
|
|
@ -124,11 +125,19 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
if (input.RemoteIntakeFin)
|
if (input.RemoteIntakeFin)
|
||||||
{
|
{
|
||||||
_mode = Mode.Terminated;
|
_mode = Mode.Terminated;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_mode == Mode.Terminated)
|
||||||
|
{
|
||||||
|
// If we broke out of the above while loop in the Terminated
|
||||||
|
// state, we don't want to transition to the MessageBody state.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
//var resumeBody = HandleExpectContinue(callback);
|
//var resumeBody = HandleExpectContinue(callback);
|
||||||
_mode = Mode.MessageBody;
|
_mode = Mode.MessageBody;
|
||||||
Execute();
|
Execute();
|
||||||
|
|
@ -145,6 +154,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Mode.Terminated:
|
case Mode.Terminated:
|
||||||
|
ConnectionControl.End(ProduceEndType.SocketShutdownSend);
|
||||||
|
ConnectionControl.End(ProduceEndType.SocketDisconnect);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -468,5 +468,72 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ConnectionClosesWhenFinReceived()
|
||||||
|
{
|
||||||
|
using (var server = new TestServer(AppChunked))
|
||||||
|
{
|
||||||
|
using (var connection = new TestConnection())
|
||||||
|
{
|
||||||
|
await connection.SendEnd(
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"",
|
||||||
|
"Post / HTTP/1.1",
|
||||||
|
"Content-Length: 7",
|
||||||
|
"",
|
||||||
|
"Goodbye");
|
||||||
|
await connection.ReceiveEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"",
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Content-Length: 7",
|
||||||
|
"",
|
||||||
|
"Goodbye");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ConnectionClosesWhenFinReceivedBeforeRequestCompletes()
|
||||||
|
{
|
||||||
|
using (var server = new TestServer(AppChunked))
|
||||||
|
{
|
||||||
|
using (var connection = new TestConnection())
|
||||||
|
{
|
||||||
|
await connection.SendEnd(
|
||||||
|
"GET /");
|
||||||
|
await connection.ReceiveEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var connection = new TestConnection())
|
||||||
|
{
|
||||||
|
await connection.SendEnd(
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"",
|
||||||
|
"Post / HTTP/1.1");
|
||||||
|
await connection.ReceiveEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var connection = new TestConnection())
|
||||||
|
{
|
||||||
|
await connection.SendEnd(
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"",
|
||||||
|
"Post / HTTP/1.1",
|
||||||
|
"Content-Length: 7");
|
||||||
|
await connection.ReceiveEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue