Getting request body variations to work
This commit is contained in:
parent
313db3f0cf
commit
044bbb83e6
|
|
@ -45,17 +45,9 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
((Connection)state).OnRead(handle, nread);
|
((Connection)state).OnRead(handle, nread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private readonly Func<object, Task> _app;
|
|
||||||
private readonly UvStreamHandle _socket;
|
private readonly UvStreamHandle _socket;
|
||||||
|
|
||||||
private Frame _frame;
|
private Frame _frame;
|
||||||
|
|
||||||
private Action<Exception> _fault;
|
|
||||||
private Action<Frame, Exception> _frameConsumeCallback;
|
|
||||||
private Action _receiveAsyncCompleted;
|
|
||||||
private Frame _receiveAsyncCompletedFrame;
|
|
||||||
|
|
||||||
public Connection(ListenerContext context, UvStreamHandle socket) : base(context)
|
public Connection(ListenerContext context, UvStreamHandle socket) : base(context)
|
||||||
{
|
{
|
||||||
_socket = socket;
|
_socket = socket;
|
||||||
|
|
@ -64,41 +56,10 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
//_services.Trace.Event(TraceEventType.Start, TraceMessage.Connection);
|
|
||||||
|
|
||||||
SocketInput = new SocketInput(Memory);
|
SocketInput = new SocketInput(Memory);
|
||||||
SocketOutput = new SocketOutput(Thread, _socket);
|
SocketOutput = new SocketOutput(Thread, _socket);
|
||||||
|
_frame = new Frame(this);
|
||||||
_socket.ReadStart(_allocCallback, _readCallback, this);
|
_socket.ReadStart(_allocCallback, _readCallback, this);
|
||||||
|
|
||||||
//_fault = ex => { Debug.WriteLine(ex.Message); };
|
|
||||||
|
|
||||||
//_frameConsumeCallback = (frame, error) =>
|
|
||||||
//{
|
|
||||||
// if (error != null)
|
|
||||||
// {
|
|
||||||
// _fault(error);
|
|
||||||
// }
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// Go(false, frame);
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// _fault(ex);
|
|
||||||
// }
|
|
||||||
//};
|
|
||||||
|
|
||||||
//try
|
|
||||||
//{
|
|
||||||
// //_socket.Blocking = false;
|
|
||||||
// //_socket.NoDelay = true;
|
|
||||||
// Go(true, null);
|
|
||||||
//}
|
|
||||||
//catch (Exception ex)
|
|
||||||
//{
|
|
||||||
// _fault(ex);
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Libuv.uv_buf_t OnAlloc(UvStreamHandle handle, int suggestedSize)
|
private Libuv.uv_buf_t OnAlloc(UvStreamHandle handle, int suggestedSize)
|
||||||
|
|
@ -119,10 +80,6 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
SocketInput.RemoteIntakeFin = true;
|
SocketInput.RemoteIntakeFin = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_frame == null)
|
|
||||||
{
|
|
||||||
_frame = new Frame(this);
|
|
||||||
}
|
|
||||||
_frame.Consume();
|
_frame.Consume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,14 +98,26 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
switch (endType)
|
switch (endType)
|
||||||
{
|
{
|
||||||
case ProduceEndType.SocketShutdownSend:
|
case ProduceEndType.SocketShutdownSend:
|
||||||
var shutdown = new UvShutdownReq();
|
Thread.Post(
|
||||||
shutdown.Init(Thread.Loop);
|
x =>
|
||||||
shutdown.Shutdown(_socket, (req, status, state) => req.Close(), null);
|
{
|
||||||
|
var self = (Connection)x;
|
||||||
|
var shutdown = new UvShutdownReq();
|
||||||
|
shutdown.Init(self.Thread.Loop);
|
||||||
|
shutdown.Shutdown(self._socket, (req, status, state) => req.Close(), null);
|
||||||
|
},
|
||||||
|
this);
|
||||||
break;
|
break;
|
||||||
case ProduceEndType.ConnectionKeepAlive:
|
case ProduceEndType.ConnectionKeepAlive:
|
||||||
|
_frame = new Frame(this);
|
||||||
|
Thread.Post(
|
||||||
|
x => ((Frame)x).Consume(),
|
||||||
|
_frame);
|
||||||
break;
|
break;
|
||||||
case ProduceEndType.SocketDisconnect:
|
case ProduceEndType.SocketDisconnect:
|
||||||
_socket.Close();
|
Thread.Post(
|
||||||
|
x => ((UvHandle)x).Close(),
|
||||||
|
_socket);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
switch (_mode)
|
switch (_mode)
|
||||||
{
|
{
|
||||||
case Mode.StartLine:
|
case Mode.StartLine:
|
||||||
if (input.RemoteIntakeFin)
|
if (input.Buffer.Count == 0 && input.RemoteIntakeFin)
|
||||||
{
|
{
|
||||||
_mode = Mode.Terminated;
|
_mode = Mode.Terminated;
|
||||||
return;
|
return;
|
||||||
|
|
@ -95,6 +95,10 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
|
|
||||||
if (!TakeStartLine(input))
|
if (!TakeStartLine(input))
|
||||||
{
|
{
|
||||||
|
if (input.RemoteIntakeFin)
|
||||||
|
{
|
||||||
|
_mode = Mode.Terminated;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -102,7 +106,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Mode.MessageHeader:
|
case Mode.MessageHeader:
|
||||||
if (input.RemoteIntakeFin)
|
if (input.Buffer.Count == 0 && input.RemoteIntakeFin)
|
||||||
{
|
{
|
||||||
_mode = Mode.Terminated;
|
_mode = Mode.Terminated;
|
||||||
return;
|
return;
|
||||||
|
|
@ -113,16 +117,25 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
{
|
{
|
||||||
if (!TakeMessageHeader(input, out endOfHeaders))
|
if (!TakeMessageHeader(input, out endOfHeaders))
|
||||||
{
|
{
|
||||||
|
if (input.RemoteIntakeFin)
|
||||||
|
{
|
||||||
|
_mode = Mode.Terminated;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//var resumeBody = HandleExpectContinue(callback);
|
//var resumeBody = HandleExpectContinue(callback);
|
||||||
Execute();
|
|
||||||
_mode = Mode.MessageBody;
|
_mode = Mode.MessageBody;
|
||||||
|
Execute();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Mode.MessageBody:
|
case Mode.MessageBody:
|
||||||
|
if (_messageBody.LocalIntakeFin)
|
||||||
|
{
|
||||||
|
// NOTE: stop reading and resume on keepalive?
|
||||||
|
return;
|
||||||
|
}
|
||||||
_messageBody.Consume();
|
_messageBody.Consume();
|
||||||
// NOTE: keep looping?
|
// NOTE: keep looping?
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -6,24 +6,6 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Server.Kestrel.Http
|
namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
{
|
{
|
||||||
public static class DelegateExtensions
|
|
||||||
{
|
|
||||||
public static void InvokeNoThrow(this Action d)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{ d.Invoke(); }
|
|
||||||
catch
|
|
||||||
{ }
|
|
||||||
}
|
|
||||||
public static void InvokeNoThrow<T>(this Action<T> d, T arg1)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{ d.Invoke(arg1); }
|
|
||||||
catch
|
|
||||||
{ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class MessageBody : MessageBodyExchanger
|
public abstract class MessageBody : MessageBodyExchanger
|
||||||
{
|
{
|
||||||
private Action _continuation = () => { };
|
private Action _continuation = () => { };
|
||||||
|
|
@ -156,8 +138,6 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
var consumeLength = Math.Min(_neededLength, input.Buffer.Count);
|
var consumeLength = Math.Min(_neededLength, input.Buffer.Count);
|
||||||
_neededLength -= consumeLength;
|
_neededLength -= consumeLength;
|
||||||
|
|
||||||
var consumed = input.Take(consumeLength);
|
|
||||||
|
|
||||||
if (_neededLength != 0)
|
if (_neededLength != 0)
|
||||||
{
|
{
|
||||||
Intake(consumeLength);
|
Intake(consumeLength);
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
uv_loop_close _uv_loop_close;
|
uv_loop_close _uv_loop_close;
|
||||||
public void loop_close(UvLoopHandle handle)
|
public void loop_close(UvLoopHandle handle)
|
||||||
{
|
{
|
||||||
|
handle.Validate(closed: true);
|
||||||
Check(_uv_loop_close(handle.DangerousGetHandle()));
|
Check(_uv_loop_close(handle.DangerousGetHandle()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -67,6 +68,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
uv_run _uv_run;
|
uv_run _uv_run;
|
||||||
public int run(UvLoopHandle handle, int mode)
|
public int run(UvLoopHandle handle, int mode)
|
||||||
{
|
{
|
||||||
|
handle.Validate();
|
||||||
return Check(_uv_run(handle, mode));
|
return Check(_uv_run(handle, mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,6 +77,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
uv_stop _uv_stop;
|
uv_stop _uv_stop;
|
||||||
public void stop(UvLoopHandle handle)
|
public void stop(UvLoopHandle handle)
|
||||||
{
|
{
|
||||||
|
handle.Validate();
|
||||||
_uv_stop(handle);
|
_uv_stop(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -83,6 +86,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
uv_ref _uv_ref;
|
uv_ref _uv_ref;
|
||||||
public void @ref(UvHandle handle)
|
public void @ref(UvHandle handle)
|
||||||
{
|
{
|
||||||
|
handle.Validate();
|
||||||
_uv_ref(handle);
|
_uv_ref(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -91,6 +95,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
uv_unref _uv_unref;
|
uv_unref _uv_unref;
|
||||||
public void unref(UvHandle handle)
|
public void unref(UvHandle handle)
|
||||||
{
|
{
|
||||||
|
handle.Validate();
|
||||||
_uv_unref(handle);
|
_uv_unref(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -102,6 +107,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
uv_close _uv_close;
|
uv_close _uv_close;
|
||||||
public void close(UvHandle handle, uv_close_cb close_cb)
|
public void close(UvHandle handle, uv_close_cb close_cb)
|
||||||
{
|
{
|
||||||
|
handle.Validate(closed: true);
|
||||||
_uv_close(handle.DangerousGetHandle(), close_cb);
|
_uv_close(handle.DangerousGetHandle(), close_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,6 +118,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
uv_async_init _uv_async_init;
|
uv_async_init _uv_async_init;
|
||||||
public void async_init(UvLoopHandle loop, UvAsyncHandle handle, uv_async_cb cb)
|
public void async_init(UvLoopHandle loop, UvAsyncHandle handle, uv_async_cb cb)
|
||||||
{
|
{
|
||||||
|
loop.Validate();
|
||||||
|
handle.Validate();
|
||||||
Check(_uv_async_init(loop, handle, cb));
|
Check(_uv_async_init(loop, handle, cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,6 +136,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
uv_tcp_init _uv_tcp_init;
|
uv_tcp_init _uv_tcp_init;
|
||||||
public void tcp_init(UvLoopHandle loop, UvTcpHandle handle)
|
public void tcp_init(UvLoopHandle loop, UvTcpHandle handle)
|
||||||
{
|
{
|
||||||
|
loop.Validate();
|
||||||
|
handle.Validate();
|
||||||
Check(_uv_tcp_init(loop, handle));
|
Check(_uv_tcp_init(loop, handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,6 +146,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
uv_tcp_bind _uv_tcp_bind;
|
uv_tcp_bind _uv_tcp_bind;
|
||||||
public void tcp_bind(UvTcpHandle handle, ref sockaddr addr, int flags)
|
public void tcp_bind(UvTcpHandle handle, ref sockaddr addr, int flags)
|
||||||
{
|
{
|
||||||
|
handle.Validate();
|
||||||
Check(_uv_tcp_bind(handle, ref addr, flags));
|
Check(_uv_tcp_bind(handle, ref addr, flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -146,6 +157,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
uv_listen _uv_listen;
|
uv_listen _uv_listen;
|
||||||
public void listen(UvStreamHandle handle, int backlog, uv_connection_cb cb)
|
public void listen(UvStreamHandle handle, int backlog, uv_connection_cb cb)
|
||||||
{
|
{
|
||||||
|
handle.Validate();
|
||||||
Check(_uv_listen(handle, backlog, cb));
|
Check(_uv_listen(handle, backlog, cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -154,6 +166,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
uv_accept _uv_accept;
|
uv_accept _uv_accept;
|
||||||
public void accept(UvStreamHandle server, UvStreamHandle client)
|
public void accept(UvStreamHandle server, UvStreamHandle client)
|
||||||
{
|
{
|
||||||
|
server.Validate();
|
||||||
|
client.Validate();
|
||||||
Check(_uv_accept(server, client));
|
Check(_uv_accept(server, client));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,6 +180,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
uv_read_start _uv_read_start;
|
uv_read_start _uv_read_start;
|
||||||
public void read_start(UvStreamHandle handle, uv_alloc_cb alloc_cb, uv_read_cb read_cb)
|
public void read_start(UvStreamHandle handle, uv_alloc_cb alloc_cb, uv_read_cb read_cb)
|
||||||
{
|
{
|
||||||
|
handle.Validate();
|
||||||
Check(_uv_read_start(handle, alloc_cb, read_cb));
|
Check(_uv_read_start(handle, alloc_cb, read_cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -174,6 +189,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
uv_read_stop _uv_read_stop;
|
uv_read_stop _uv_read_stop;
|
||||||
public void read_stop(UvStreamHandle handle)
|
public void read_stop(UvStreamHandle handle)
|
||||||
{
|
{
|
||||||
|
handle.Validate();
|
||||||
Check(_uv_read_stop(handle));
|
Check(_uv_read_stop(handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -182,6 +198,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
uv_try_write _uv_try_write;
|
uv_try_write _uv_try_write;
|
||||||
public int try_write(UvStreamHandle handle, Libuv.uv_buf_t[] bufs, int nbufs)
|
public int try_write(UvStreamHandle handle, Libuv.uv_buf_t[] bufs, int nbufs)
|
||||||
{
|
{
|
||||||
|
handle.Validate();
|
||||||
return Check(_uv_try_write(handle, bufs, nbufs));
|
return Check(_uv_try_write(handle, bufs, nbufs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -192,6 +209,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
uv_write _uv_write;
|
uv_write _uv_write;
|
||||||
public void write(UvWriteReq req, UvStreamHandle handle, Libuv.uv_buf_t[] bufs, int nbufs, uv_write_cb cb)
|
public void write(UvWriteReq req, UvStreamHandle handle, Libuv.uv_buf_t[] bufs, int nbufs, uv_write_cb cb)
|
||||||
{
|
{
|
||||||
|
req.Validate();
|
||||||
|
handle.Validate();
|
||||||
Check(_uv_write(req, handle, bufs, nbufs, cb));
|
Check(_uv_write(req, handle, bufs, nbufs, cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,6 +221,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
uv_shutdown _uv_shutdown;
|
uv_shutdown _uv_shutdown;
|
||||||
public void shutdown(UvShutdownReq req, UvStreamHandle handle, uv_shutdown_cb cb)
|
public void shutdown(UvShutdownReq req, UvStreamHandle handle, uv_shutdown_cb cb)
|
||||||
{
|
{
|
||||||
|
req.Validate();
|
||||||
|
handle.Validate();
|
||||||
Check(_uv_shutdown(req, handle, cb));
|
Check(_uv_shutdown(req, handle, cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,6 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
{
|
{
|
||||||
static Libuv.uv_close_cb _close_cb = DestroyHandle;
|
static Libuv.uv_close_cb _close_cb = DestroyHandle;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected override bool ReleaseHandle()
|
protected override bool ReleaseHandle()
|
||||||
{
|
{
|
||||||
var memory = handle;
|
var memory = handle;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
#define TRACE
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Server.Kestrel.Networking
|
namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
{
|
{
|
||||||
|
|
@ -12,6 +14,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
public abstract class UvMemory : SafeHandle
|
public abstract class UvMemory : SafeHandle
|
||||||
{
|
{
|
||||||
protected Libuv _uv;
|
protected Libuv _uv;
|
||||||
|
int _threadId;
|
||||||
|
|
||||||
public UvMemory() : base(IntPtr.Zero, true)
|
public UvMemory() : base(IntPtr.Zero, true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -29,6 +33,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
unsafe protected void CreateHandle(Libuv uv, int size)
|
unsafe protected void CreateHandle(Libuv uv, int size)
|
||||||
{
|
{
|
||||||
_uv = uv;
|
_uv = uv;
|
||||||
|
_threadId = Thread.CurrentThread.ManagedThreadId;
|
||||||
|
|
||||||
handle = Marshal.AllocCoTaskMem(size);
|
handle = Marshal.AllocCoTaskMem(size);
|
||||||
*(IntPtr*)handle = GCHandle.ToIntPtr(GCHandle.Alloc(this));
|
*(IntPtr*)handle = GCHandle.ToIntPtr(GCHandle.Alloc(this));
|
||||||
}
|
}
|
||||||
|
|
@ -36,8 +42,17 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
protected void CreateHandle(UvLoopHandle loop, int size)
|
protected void CreateHandle(UvLoopHandle loop, int size)
|
||||||
{
|
{
|
||||||
CreateHandle(loop._uv, size);
|
CreateHandle(loop._uv, size);
|
||||||
|
_threadId = loop._threadId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Validate(bool closed = false)
|
||||||
|
{
|
||||||
|
Trace.Assert(IsClosed == closed, "Handle is closed");
|
||||||
|
Trace.Assert(!IsInvalid, "Handle is invalid");
|
||||||
|
Trace.Assert(_threadId == Thread.CurrentThread.ManagedThreadId, "ThreadId is correct");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
unsafe protected static void DestroyHandle(IntPtr memory)
|
unsafe protected static void DestroyHandle(IntPtr memory)
|
||||||
{
|
{
|
||||||
var gcHandlePtr = *(IntPtr*)memory;
|
var gcHandlePtr = *(IntPtr*)memory;
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
|
|
||||||
public void Init(UvLoopHandle loop)
|
public void Init(UvLoopHandle loop)
|
||||||
{
|
{
|
||||||
CreateHandle(loop.Libuv, loop.Libuv.req_size(3));
|
CreateHandle(loop, loop.Libuv.req_size(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Shutdown(UvStreamHandle handle, Action<UvShutdownReq, int, object> callback, object state)
|
public void Shutdown(UvStreamHandle handle, Action<UvShutdownReq, int, object> callback, object state)
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
|
|
||||||
public void Init(UvLoopHandle loop)
|
public void Init(UvLoopHandle loop)
|
||||||
{
|
{
|
||||||
CreateHandle(loop.Libuv, loop.Libuv.req_size(2));
|
CreateHandle(loop, loop.Libuv.req_size(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(UvStreamHandle handle, Libuv.uv_buf_t[] bufs, int nbufs, Action<UvWriteReq, int, object> callback, object state)
|
public void Write(UvStreamHandle handle, Libuv.uv_buf_t[] bufs, int nbufs, Action<UvWriteReq, int, object> callback, object state)
|
||||||
|
|
@ -39,14 +39,6 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
|
|
||||||
public abstract class UvReq : UvMemory
|
public abstract class UvReq : UvMemory
|
||||||
{
|
{
|
||||||
|
|
||||||
unsafe protected void CreateHandle(Libuv uv, int size)
|
|
||||||
{
|
|
||||||
_uv = uv;
|
|
||||||
handle = Marshal.AllocCoTaskMem(size);
|
|
||||||
*(IntPtr*)handle = GCHandle.ToIntPtr(GCHandle.Alloc(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool ReleaseHandle()
|
protected override bool ReleaseHandle()
|
||||||
{
|
{
|
||||||
DestroyHandle(handle);
|
DestroyHandle(handle);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace SampleApp
|
namespace SampleApp
|
||||||
|
|
@ -17,6 +18,8 @@ namespace SampleApp
|
||||||
engine.Stop();
|
engine.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static async Task App(object arg)
|
private static async Task App(object arg)
|
||||||
{
|
{
|
||||||
var httpContext = new Microsoft.AspNet.PipelineCore.DefaultHttpContext(
|
var httpContext = new Microsoft.AspNet.PipelineCore.DefaultHttpContext(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using Microsoft.AspNet.HttpFeature;
|
using Microsoft.AspNet.HttpFeature;
|
||||||
using Microsoft.AspNet.Server.Kestrel;
|
using Microsoft.AspNet.Server.Kestrel;
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
@ -29,6 +30,25 @@ namespace Microsoft.AspNet.Server.KestralTests
|
||||||
await response.Body.WriteAsync(buffer, 0, count);
|
await response.Body.WriteAsync(buffer, 0, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private async Task AppChunked(object callContext)
|
||||||
|
{
|
||||||
|
var request = callContext as IHttpRequestFeature;
|
||||||
|
var response = callContext as IHttpResponseFeature;
|
||||||
|
response.Headers["Transfer-Encoding"] = new[] { "chunked" };
|
||||||
|
for (; ;)
|
||||||
|
{
|
||||||
|
var buffer = new byte[8192];
|
||||||
|
var count = await request.Body.ReadAsync(buffer, 0, buffer.Length);
|
||||||
|
var hex = Encoding.ASCII.GetBytes(count.ToString("x") + "\r\n");
|
||||||
|
await response.Body.WriteAsync(hex, 0, hex.Length);
|
||||||
|
if (count == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
await response.Body.WriteAsync(buffer, 0, count);
|
||||||
|
await response.Body.WriteAsync(new[] { (byte)'\r', (byte)'\n' }, 0, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task EngineCanStartAndStop()
|
public async Task EngineCanStartAndStop()
|
||||||
|
|
@ -70,5 +90,187 @@ namespace Microsoft.AspNet.Server.KestralTests
|
||||||
started.Dispose();
|
started.Dispose();
|
||||||
engine.Stop();
|
engine.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Http10()
|
||||||
|
{
|
||||||
|
var engine = new KestrelEngine();
|
||||||
|
engine.Start(1);
|
||||||
|
var started = engine.CreateServer(App);
|
||||||
|
|
||||||
|
Transceive(
|
||||||
|
@"POST / HTTP/1.0
|
||||||
|
|
||||||
|
Hello World",
|
||||||
|
@"HTTP/1.0 200 OK
|
||||||
|
|
||||||
|
Hello World");
|
||||||
|
started.Dispose();
|
||||||
|
engine.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Http10ContentLength()
|
||||||
|
{
|
||||||
|
var engine = new KestrelEngine();
|
||||||
|
engine.Start(1);
|
||||||
|
var started = engine.CreateServer(App);
|
||||||
|
|
||||||
|
Transceive(
|
||||||
|
@"POST / HTTP/1.0
|
||||||
|
Content-Length: 5
|
||||||
|
|
||||||
|
Hello World",
|
||||||
|
@"HTTP/1.0 200 OK
|
||||||
|
|
||||||
|
Hello");
|
||||||
|
started.Dispose();
|
||||||
|
engine.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Http10TransferEncoding()
|
||||||
|
{
|
||||||
|
var engine = new KestrelEngine();
|
||||||
|
engine.Start(1);
|
||||||
|
var started = engine.CreateServer(App);
|
||||||
|
|
||||||
|
Transceive(
|
||||||
|
@"POST / HTTP/1.0
|
||||||
|
Transfer-Encoding: chunked
|
||||||
|
|
||||||
|
5
|
||||||
|
Hello
|
||||||
|
6
|
||||||
|
World
|
||||||
|
0
|
||||||
|
ignored",
|
||||||
|
@"HTTP/1.0 200 OK
|
||||||
|
|
||||||
|
Hello World");
|
||||||
|
started.Dispose();
|
||||||
|
engine.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Http10KeepAlive()
|
||||||
|
{
|
||||||
|
var engine = new KestrelEngine();
|
||||||
|
engine.Start(1);
|
||||||
|
var started = engine.CreateServer(AppChunked);
|
||||||
|
|
||||||
|
Transceive(
|
||||||
|
@"GET / HTTP/1.0
|
||||||
|
Connection: Keep-Alive
|
||||||
|
|
||||||
|
POST / HTTP/1.0
|
||||||
|
|
||||||
|
Goodbye",
|
||||||
|
@"HTTP/1.0 200 OK
|
||||||
|
Transfer-Encoding: chunked
|
||||||
|
Connection: keep-alive
|
||||||
|
|
||||||
|
0
|
||||||
|
HTTP/1.0 200 OK
|
||||||
|
Transfer-Encoding: chunked
|
||||||
|
|
||||||
|
7
|
||||||
|
Goodbye
|
||||||
|
0
|
||||||
|
");
|
||||||
|
started.Dispose();
|
||||||
|
engine.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Http10KeepAliveContentLength()
|
||||||
|
{
|
||||||
|
var engine = new KestrelEngine();
|
||||||
|
engine.Start(1);
|
||||||
|
var started = engine.CreateServer(AppChunked);
|
||||||
|
|
||||||
|
Transceive(
|
||||||
|
@"POST / HTTP/1.0
|
||||||
|
Connection: Keep-Alive
|
||||||
|
Content-Length: 11
|
||||||
|
|
||||||
|
Hello WorldPOST / HTTP/1.0
|
||||||
|
|
||||||
|
Goodbye",
|
||||||
|
@"HTTP/1.0 200 OK
|
||||||
|
Transfer-Encoding: chunked
|
||||||
|
Connection: keep-alive
|
||||||
|
|
||||||
|
b
|
||||||
|
Hello World
|
||||||
|
0
|
||||||
|
HTTP/1.0 200 OK
|
||||||
|
Transfer-Encoding: chunked
|
||||||
|
|
||||||
|
7
|
||||||
|
Goodbye
|
||||||
|
0
|
||||||
|
");
|
||||||
|
started.Dispose();
|
||||||
|
engine.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Http10KeepAliveTransferEncoding()
|
||||||
|
{
|
||||||
|
var engine = new KestrelEngine();
|
||||||
|
engine.Start(1);
|
||||||
|
var started = engine.CreateServer(AppChunked);
|
||||||
|
|
||||||
|
Transceive(
|
||||||
|
@"POST / HTTP/1.0
|
||||||
|
Transfer-Encoding: chunked
|
||||||
|
Connection: keep-alive
|
||||||
|
|
||||||
|
5
|
||||||
|
Hello
|
||||||
|
6
|
||||||
|
World
|
||||||
|
0
|
||||||
|
POST / HTTP/1.0
|
||||||
|
|
||||||
|
Goodbye",
|
||||||
|
@"HTTP/1.0 200 OK
|
||||||
|
Transfer-Encoding: chunked
|
||||||
|
Connection: keep-alive
|
||||||
|
|
||||||
|
b
|
||||||
|
Hello World
|
||||||
|
0
|
||||||
|
HTTP/1.0 200 OK
|
||||||
|
Transfer-Encoding: chunked
|
||||||
|
|
||||||
|
7
|
||||||
|
Goodbye
|
||||||
|
0
|
||||||
|
");
|
||||||
|
started.Dispose();
|
||||||
|
engine.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void Transceive(string send, string expected)
|
||||||
|
{
|
||||||
|
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||||
|
socket.Connect(new IPEndPoint(IPAddress.Loopback, 4001));
|
||||||
|
|
||||||
|
var stream = new NetworkStream(socket, false);
|
||||||
|
var writer = new StreamWriter(stream, Encoding.ASCII);
|
||||||
|
writer.Write(send);
|
||||||
|
writer.Flush();
|
||||||
|
stream.Flush();
|
||||||
|
socket.Shutdown(SocketShutdown.Send);
|
||||||
|
|
||||||
|
var reader = new StreamReader(stream, Encoding.ASCII);
|
||||||
|
var actual = reader.ReadToEnd();
|
||||||
|
|
||||||
|
Assert.Equal(expected, actual);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,9 @@
|
||||||
"Microsoft.AspNet.Server.Kestrel": "0.1-*"
|
"Microsoft.AspNet.Server.Kestrel": "0.1-*"
|
||||||
},
|
},
|
||||||
"configurations": {
|
"configurations": {
|
||||||
"net45": {}
|
"net45": {
|
||||||
|
"compilationOptions": { "define": [ "TRACE" ] }
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"commands": {
|
"commands": {
|
||||||
"run": "Xunit.KRunner",
|
"run": "Xunit.KRunner",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue