Ensure clients connecting to Kestrel's dispatch pipe are listeners
This commit is contained in:
parent
84cf678905
commit
eee9520ffd
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure;
|
||||
|
|
@ -75,15 +76,19 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
|
|||
try
|
||||
{
|
||||
pipe.Accept(dispatchPipe);
|
||||
|
||||
// Ensure client sends "Kestrel" before adding pipe to _dispatchPipes.
|
||||
var readContext = new PipeReadContext(this);
|
||||
dispatchPipe.ReadStart(
|
||||
(handle, status2, state) => ((PipeReadContext)state).AllocCallback(handle, status2),
|
||||
(handle, status2, state) => ((PipeReadContext)state).ReadCallback(handle, status2),
|
||||
readContext);
|
||||
}
|
||||
catch (UvException ex)
|
||||
{
|
||||
dispatchPipe.Dispose();
|
||||
Log.LogError(0, ex, "ListenerPrimary.OnListenPipe");
|
||||
return;
|
||||
}
|
||||
|
||||
_dispatchPipes.Add(dispatchPipe);
|
||||
}
|
||||
|
||||
protected override void DispatchConnection(UvStreamHandle socket)
|
||||
|
|
@ -179,5 +184,55 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
|
|||
}, this).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private class PipeReadContext
|
||||
{
|
||||
private readonly ListenerPrimary _listener;
|
||||
private readonly IntPtr _bufPtr;
|
||||
private GCHandle _bufHandle;
|
||||
private int _bytesRead;
|
||||
|
||||
public PipeReadContext(ListenerPrimary listener)
|
||||
{
|
||||
_listener = listener;
|
||||
_bufHandle = GCHandle.Alloc(new byte[8], GCHandleType.Pinned);
|
||||
_bufPtr = _bufHandle.AddrOfPinnedObject();
|
||||
}
|
||||
|
||||
public Libuv.uv_buf_t AllocCallback(UvStreamHandle dispatchPipe, int suggestedSize)
|
||||
{
|
||||
return dispatchPipe.Libuv.buf_init(_bufPtr + _bytesRead, 8 - _bytesRead);
|
||||
}
|
||||
|
||||
public unsafe void ReadCallback(UvStreamHandle dispatchPipe, int status)
|
||||
{
|
||||
try
|
||||
{
|
||||
dispatchPipe.Libuv.Check(status);
|
||||
|
||||
_bytesRead += status;
|
||||
|
||||
if (_bytesRead == 8)
|
||||
{
|
||||
if (*(ulong*)_bufPtr == Constants.PipeMessage)
|
||||
{
|
||||
_listener._dispatchPipes.Add((UvPipeHandle) dispatchPipe);
|
||||
dispatchPipe.ReadStop();
|
||||
_bufHandle.Free();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IOException("Bad data sent over Kestrel pipe.");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
dispatchPipe.Dispose();
|
||||
_bufHandle.Free();
|
||||
_listener.Log.LogError(0, ex, "ListenerPrimary.ReadCallback");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
|
|||
/// </summary>
|
||||
public abstract class ListenerSecondary : ListenerContext, IAsyncDisposable
|
||||
{
|
||||
private static ArraySegment<ArraySegment<byte>> _pipeMessage =
|
||||
new ArraySegment<ArraySegment<byte>>(new[] { new ArraySegment<byte>(BitConverter.GetBytes(Constants.PipeMessage)) });
|
||||
|
||||
private string _pipeName;
|
||||
private IntPtr _ptr;
|
||||
private Libuv.uv_buf_t _buf;
|
||||
|
|
@ -89,6 +92,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
|
|||
return;
|
||||
}
|
||||
|
||||
var writeReq = new UvWriteReq(Log);
|
||||
|
||||
try
|
||||
{
|
||||
DispatchPipe.ReadStart(
|
||||
|
|
@ -96,10 +101,28 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
|
|||
(handle, status2, state) => ((ListenerSecondary)state).ReadStartCallback(handle, status2),
|
||||
this);
|
||||
|
||||
tcs.SetResult(0);
|
||||
writeReq.Init(Thread.Loop);
|
||||
writeReq.Write(
|
||||
DispatchPipe,
|
||||
_pipeMessage,
|
||||
(req, status2, ex, state) =>
|
||||
{
|
||||
req.Dispose();
|
||||
|
||||
if (ex != null)
|
||||
{
|
||||
tcs.SetException(ex);
|
||||
}
|
||||
else
|
||||
{
|
||||
tcs.SetResult(0);
|
||||
}
|
||||
},
|
||||
tcs);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
writeReq.Dispose();
|
||||
DispatchPipe.Dispose();
|
||||
tcs.SetException(ex);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
|
|||
|
||||
public const string ServerName = "Kestrel";
|
||||
|
||||
// "Kestrel\0"
|
||||
public const ulong PipeMessage = 0x006C65727473654B;
|
||||
|
||||
private static int? GetECONNRESET()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
|
|
|
|||
|
|
@ -85,18 +85,30 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking
|
|||
_callback = null;
|
||||
_state = null;
|
||||
Unpin(this);
|
||||
|
||||
var block = start.Block;
|
||||
for (var index = 0; index < nBuffers; index++)
|
||||
{
|
||||
block = block.Next;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe void Write2(
|
||||
public void Write(
|
||||
UvStreamHandle handle,
|
||||
ArraySegment<ArraySegment<byte>> bufs,
|
||||
Action<UvWriteReq, int, Exception, object> callback,
|
||||
object state)
|
||||
{
|
||||
WriteArraySegmentInternal(handle, bufs, sendHandle: null, callback: callback, state: state);
|
||||
}
|
||||
|
||||
public void Write2(
|
||||
UvStreamHandle handle,
|
||||
ArraySegment<ArraySegment<byte>> bufs,
|
||||
UvStreamHandle sendHandle,
|
||||
Action<UvWriteReq, int, Exception, object> callback,
|
||||
object state)
|
||||
{
|
||||
WriteArraySegmentInternal(handle, bufs, sendHandle, callback, state);
|
||||
}
|
||||
|
||||
private unsafe void WriteArraySegmentInternal(
|
||||
UvStreamHandle handle,
|
||||
ArraySegment<ArraySegment<byte>> bufs,
|
||||
UvStreamHandle sendHandle,
|
||||
|
|
@ -133,7 +145,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking
|
|||
|
||||
_callback = callback;
|
||||
_state = state;
|
||||
_uv.write2(this, handle, pBuffers, nBuffers, sendHandle, _uv_write_cb);
|
||||
|
||||
if (sendHandle == null)
|
||||
{
|
||||
_uv.write(this, handle, pBuffers, nBuffers, _uv_write_cb);
|
||||
}
|
||||
else
|
||||
{
|
||||
_uv.write2(this, handle, pBuffers, nBuffers, sendHandle, _uv_write_cb);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue