parent
1406ec94c3
commit
de6c32dc4b
|
|
@ -53,11 +53,9 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
|
|
||||||
SocketOutput _self;
|
SocketOutput _self;
|
||||||
ArraySegment<byte> _buffer;
|
ArraySegment<byte> _buffer;
|
||||||
Action<Exception> _drained;
|
|
||||||
UvStreamHandle _socket;
|
UvStreamHandle _socket;
|
||||||
Action<Exception, object> _callback;
|
Action<Exception, object> _callback;
|
||||||
object _state;
|
object _state;
|
||||||
GCHandle _pin;
|
|
||||||
|
|
||||||
internal void Contextualize(
|
internal void Contextualize(
|
||||||
SocketOutput socketOutput,
|
SocketOutput socketOutput,
|
||||||
|
|
@ -87,8 +85,14 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
{
|
{
|
||||||
KestrelTrace.Log.ConnectionWriteCallback(0, status);
|
KestrelTrace.Log.ConnectionWriteCallback(0, status);
|
||||||
//NOTE: pool this?
|
//NOTE: pool this?
|
||||||
|
|
||||||
|
var callback = _callback;
|
||||||
|
_callback = null;
|
||||||
|
var state = _state;
|
||||||
|
_state = null;
|
||||||
|
|
||||||
Dispose();
|
Dispose();
|
||||||
_callback(error, _state);
|
callback(error, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,10 +37,27 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
|
|
||||||
public void Listen(int backlog, Action<UvStreamHandle, int, Exception, object> callback, object state)
|
public void Listen(int backlog, Action<UvStreamHandle, int, Exception, object> callback, object state)
|
||||||
{
|
{
|
||||||
_listenCallback = callback;
|
if (_listenVitality.IsAllocated)
|
||||||
_listenState = state;
|
{
|
||||||
_listenVitality = GCHandle.Alloc(this, GCHandleType.Normal);
|
throw new InvalidOperationException("TODO: Listen may not be called more than once");
|
||||||
_uv.listen(this, 10, _uv_connection_cb);
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_listenCallback = callback;
|
||||||
|
_listenState = state;
|
||||||
|
_listenVitality = GCHandle.Alloc(this, GCHandleType.Normal);
|
||||||
|
_uv.listen(this, 10, _uv_connection_cb);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
_listenCallback = null;
|
||||||
|
_listenState = null;
|
||||||
|
if (_listenVitality.IsAllocated)
|
||||||
|
{
|
||||||
|
_listenVitality.Free();
|
||||||
|
}
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Accept(UvStreamHandle handle)
|
public void Accept(UvStreamHandle handle)
|
||||||
|
|
@ -53,15 +70,37 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
Action<UvStreamHandle, int, Exception, object> readCallback,
|
Action<UvStreamHandle, int, Exception, object> readCallback,
|
||||||
object state)
|
object state)
|
||||||
{
|
{
|
||||||
_allocCallback = allocCallback;
|
if (_readVitality.IsAllocated)
|
||||||
_readCallback = readCallback;
|
{
|
||||||
_readState = state;
|
throw new InvalidOperationException("TODO: ReadStop must be called before ReadStart may be called again");
|
||||||
_readVitality = GCHandle.Alloc(this, GCHandleType.Normal);
|
}
|
||||||
_uv.read_start(this, _uv_alloc_cb, _uv_read_cb);
|
try
|
||||||
|
{
|
||||||
|
_allocCallback = allocCallback;
|
||||||
|
_readCallback = readCallback;
|
||||||
|
_readState = state;
|
||||||
|
_readVitality = GCHandle.Alloc(this, GCHandleType.Normal);
|
||||||
|
_uv.read_start(this, _uv_alloc_cb, _uv_read_cb);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
_allocCallback = null;
|
||||||
|
_readCallback = null;
|
||||||
|
_readState = null;
|
||||||
|
if (_readVitality.IsAllocated)
|
||||||
|
{
|
||||||
|
_readVitality.Free();
|
||||||
|
}
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReadStop()
|
public void ReadStop()
|
||||||
{
|
{
|
||||||
|
if (!_readVitality.IsAllocated)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("TODO: ReadStart must be called before ReadStop may be called");
|
||||||
|
}
|
||||||
_allocCallback = null;
|
_allocCallback = null;
|
||||||
_readCallback = null;
|
_readCallback = null;
|
||||||
_readState = null;
|
_readState = null;
|
||||||
|
|
|
||||||
|
|
@ -40,45 +40,60 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
Action<UvWriteReq, int, Exception, object> callback,
|
Action<UvWriteReq, int, Exception, object> callback,
|
||||||
object state)
|
object state)
|
||||||
{
|
{
|
||||||
// add GCHandle to keeps this SafeHandle alive while request processing
|
try
|
||||||
_pins.Add(GCHandle.Alloc(this, GCHandleType.Normal));
|
|
||||||
|
|
||||||
var pBuffers = (Libuv.uv_buf_t*)_bufs;
|
|
||||||
var nBuffers = bufs.Count;
|
|
||||||
if (nBuffers > BUFFER_COUNT)
|
|
||||||
{
|
{
|
||||||
// create and pin buffer array when it's larger than the pre-allocated one
|
// add GCHandle to keeps this SafeHandle alive while request processing
|
||||||
var bufArray = new Libuv.uv_buf_t[nBuffers];
|
_pins.Add(GCHandle.Alloc(this, GCHandleType.Normal));
|
||||||
var gcHandle = GCHandle.Alloc(bufArray, GCHandleType.Pinned);
|
|
||||||
_pins.Add(gcHandle);
|
|
||||||
pBuffers = (Libuv.uv_buf_t*)gcHandle.AddrOfPinnedObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var index = 0; index != nBuffers; ++index)
|
var pBuffers = (Libuv.uv_buf_t*)_bufs;
|
||||||
|
var nBuffers = bufs.Count;
|
||||||
|
if (nBuffers > BUFFER_COUNT)
|
||||||
|
{
|
||||||
|
// create and pin buffer array when it's larger than the pre-allocated one
|
||||||
|
var bufArray = new Libuv.uv_buf_t[nBuffers];
|
||||||
|
var gcHandle = GCHandle.Alloc(bufArray, GCHandleType.Pinned);
|
||||||
|
_pins.Add(gcHandle);
|
||||||
|
pBuffers = (Libuv.uv_buf_t*)gcHandle.AddrOfPinnedObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var index = 0; index != nBuffers; ++index)
|
||||||
|
{
|
||||||
|
// create and pin each segment being written
|
||||||
|
var buf = bufs.Array[bufs.Offset + index];
|
||||||
|
|
||||||
|
var gcHandle = GCHandle.Alloc(buf.Array, GCHandleType.Pinned);
|
||||||
|
_pins.Add(gcHandle);
|
||||||
|
pBuffers[index] = Libuv.buf_init(
|
||||||
|
gcHandle.AddrOfPinnedObject() + buf.Offset,
|
||||||
|
buf.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
_callback = callback;
|
||||||
|
_state = state;
|
||||||
|
_uv.write(this, handle, pBuffers, nBuffers, _uv_write_cb);
|
||||||
|
}
|
||||||
|
catch
|
||||||
{
|
{
|
||||||
// create and pin each segment being written
|
_callback = null;
|
||||||
var buf = bufs.Array[bufs.Offset + index];
|
_state = null;
|
||||||
|
Unpin(this);
|
||||||
var gcHandle = GCHandle.Alloc(buf.Array, GCHandleType.Pinned);
|
throw;
|
||||||
_pins.Add(gcHandle);
|
|
||||||
pBuffers[index] = Libuv.buf_init(
|
|
||||||
gcHandle.AddrOfPinnedObject() + buf.Offset,
|
|
||||||
buf.Count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_callback = callback;
|
|
||||||
_state = state;
|
|
||||||
_uv.write(this, handle, pBuffers, nBuffers, _uv_write_cb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void UvWriteCb(IntPtr ptr, int status)
|
private static void Unpin(UvWriteReq req)
|
||||||
{
|
{
|
||||||
var req = FromIntPtr<UvWriteReq>(ptr);
|
|
||||||
foreach (var pin in req._pins)
|
foreach (var pin in req._pins)
|
||||||
{
|
{
|
||||||
pin.Free();
|
pin.Free();
|
||||||
}
|
}
|
||||||
req._pins.Clear();
|
req._pins.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UvWriteCb(IntPtr ptr, int status)
|
||||||
|
{
|
||||||
|
var req = FromIntPtr<UvWriteReq>(ptr);
|
||||||
|
Unpin(req);
|
||||||
|
|
||||||
var callback = req._callback;
|
var callback = req._callback;
|
||||||
req._callback = null;
|
req._callback = null;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue