private UvPipeHandle AcceptPipe() { var pipe = new UvPipeHandle(TransportContext.Log); try { pipe.Init(Thread.Loop, Thread.QueueCloseHandle); } catch { pipe.Dispose(); throw; } return(pipe); }
/// <summary> /// Handles an incoming connection /// </summary> /// <param name="listenSocket">Socket being used to listen on</param> /// <param name="status">Connection status</param> protected override void OnConnection(UvStreamHandle listenSocket, int status) { var acceptSocket = new UvPipeHandle(Log); try { acceptSocket.Init(Thread.Loop, false); listenSocket.Accept(acceptSocket); DispatchConnection(acceptSocket); } catch (UvException ex) { Log.LogError("PipeListener.OnConnection", ex); acceptSocket.Dispose(); return; } }
/// <summary> /// Creates the socket used to listen for incoming connections /// </summary> protected override UvStreamHandle CreateListenSocket() { var socket = new UvPipeHandle(Log); try { socket.Init(Thread.Loop, Thread.QueueCloseHandle, false); socket.Bind(ServerAddress.UnixPipePath); } catch { socket.Dispose(); throw; } return(socket); }
public async Task StartAsync( string pipeName, string scheme, string host, int port, KestrelThread thread, Func <Frame, Task> application) { await StartAsync(scheme, host, port, thread, application).ConfigureAwait(false); await Thread.PostAsync(_ => { ListenPipe = new UvPipeHandle(Log); ListenPipe.Init(Thread.Loop, false); ListenPipe.Bind(pipeName); ListenPipe.Listen(Constants.ListenBacklog, OnListenPipe, null); }, null).ConfigureAwait(false); }
private void PostListenHandleToLoop(object tcsObj) { TaskCompletionSource <int> taskCompletionSource = (TaskCompletionSource <int>)tcsObj; if (string.IsNullOrEmpty(_name)) { taskCompletionSource.SetResult(0); return; } IntPtr intPtr = Marshal.AllocHGlobal(4); _bufferStruct = _libuv.CreateBufferStruct(intPtr, 4); _uvPipeHandle = new UvPipeHandle(); _uvPipeHandle.Init(_loopHandle, true); UvPipeStream uvPipeStream = new UvPipeStream(); uvPipeStream.Init(_loopHandle); //链接 uvPipeStream.PipeConnect(_uvPipeHandle, _name, new Action <UvPipeStream, int, Exception, object>(ConnectionCallBack), taskCompletionSource); }
private void OnListenPipe(UvStreamHandle pipe, int status, Exception error) { if (status < 0) { return; } var dispatchPipe = new UvPipeHandle(Log); dispatchPipe.Init(Thread.Loop, Thread.QueueCloseHandle, true); try { pipe.Accept(dispatchPipe); } catch (UvException ex) { dispatchPipe.Dispose(); Log.LogError(0, ex, "ListenerPrimary.OnListenPipe"); return; } _dispatchPipes.Add(dispatchPipe); }
/// <summary> /// 管道连接 /// </summary> /// <param name="uvStreamHandle"></param> /// <param name="num"></param> /// <param name="ex"></param> /// <param name="obj"></param> private unsafe void PipeConnectionCallBack(UvStreamHandle uvStreamHandle, int num, Exception ex, object obj) { if (num < 0) { return; } UvPipeHandle uvPipeHandle = new UvPipeHandle(); uvPipeHandle.Init(_loopHandle, true); try { uvStreamHandle.Accept(uvPipeHandle); } catch (Exception) { uvPipeHandle.Dispose(); return; } if (_uvPipeHandleOffset > 0) // 是windows系统 { *(int *)((void *)(uvPipeHandle.InternalGetHandle() + _uvPipeHandleOffset)) = _currentProcessId; } _pipeHandleList.Add(uvPipeHandle); }
private void OnListenPipe(UvStreamHandle pipe, int status, Exception error) { if (status < 0) { return; } var dispatchPipe = new UvPipeHandle(); dispatchPipe.Init(Thread.Loop, Thread.QueueCloseHandle, true); try { pipe.Accept(dispatchPipe); } catch (UvException ex) { dispatchPipe.Dispose(); Service.Logger.Log(ex); return; } _dispatchPipes.Add(dispatchPipe); }
public async Task NonListenerPipeConnectionsAreLoggedAndIgnored() { var libuv = new LibuvFunctions(); var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0)); var logger = new TestApplicationErrorLogger(); var serviceContextPrimary = new TestServiceContext(); var builderPrimary = new ConnectionBuilder(); builderPrimary.UseHttpServer(serviceContextPrimary, new DummyApplication(c => c.Response.WriteAsync("Primary")), HttpProtocols.Http1); var transportContextPrimary = new TestLibuvTransportContext() { Log = new LibuvTrace(logger) }; transportContextPrimary.ConnectionDispatcher = new ConnectionDispatcher(serviceContextPrimary, builderPrimary.Build()); var serviceContextSecondary = new TestServiceContext { DateHeaderValueManager = serviceContextPrimary.DateHeaderValueManager, ServerOptions = serviceContextPrimary.ServerOptions, Scheduler = serviceContextPrimary.Scheduler, HttpParser = serviceContextPrimary.HttpParser, }; var builderSecondary = new ConnectionBuilder(); builderSecondary.UseHttpServer(serviceContextSecondary, new DummyApplication(c => c.Response.WriteAsync("Secondary")), HttpProtocols.Http1); var transportContextSecondary = new TestLibuvTransportContext(); transportContextSecondary.ConnectionDispatcher = new ConnectionDispatcher(serviceContextSecondary, builderSecondary.Build()); var libuvTransport = new LibuvTransport(libuv, transportContextPrimary, listenOptions); var pipeName = (libuv.IsWindows ? @"\\.\pipe\kestrel_" : "/tmp/kestrel_") + Guid.NewGuid().ToString("n"); var pipeMessage = Guid.NewGuid().ToByteArray(); // Start primary listener var libuvThreadPrimary = new LibuvThread(libuvTransport); await libuvThreadPrimary.StartAsync(); var listenerPrimary = new ListenerPrimary(transportContextPrimary); await listenerPrimary.StartAsync(pipeName, pipeMessage, listenOptions, libuvThreadPrimary); var address = GetUri(listenOptions); // Add secondary listener var libuvThreadSecondary = new LibuvThread(libuvTransport); await libuvThreadSecondary.StartAsync(); var listenerSecondary = new ListenerSecondary(transportContextSecondary); await listenerSecondary.StartAsync(pipeName, pipeMessage, listenOptions, libuvThreadSecondary); // TCP Connections get round-robined await AssertResponseEventually(address, "Secondary", allowed : new[] { "Primary" }); Assert.Equal("Primary", await HttpClientSlim.GetStringAsync(address)); // Create a pipe connection and keep it open without sending any data var connectTcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously); var connectionTrace = new LibuvTrace(new TestApplicationErrorLogger()); var pipe = new UvPipeHandle(connectionTrace); libuvThreadPrimary.Post(_ => { var connectReq = new UvConnectRequest(connectionTrace); pipe.Init(libuvThreadPrimary.Loop, libuvThreadPrimary.QueueCloseHandle); connectReq.Init(libuvThreadPrimary); connectReq.Connect( pipe, pipeName, (req, status, ex, __) => { req.Dispose(); if (ex != null) { connectTcs.SetException(ex); } else { connectTcs.SetResult(null); } }, null); }, (object)null); await connectTcs.Task; // TCP connections will still get round-robined between only the two listeners Assert.Equal("Secondary", await HttpClientSlim.GetStringAsync(address)); Assert.Equal("Primary", await HttpClientSlim.GetStringAsync(address)); Assert.Equal("Secondary", await HttpClientSlim.GetStringAsync(address)); await libuvThreadPrimary.PostAsync(_ => pipe.Dispose(), (object)null); // Wait up to 10 seconds for error to be logged for (var i = 0; i < 10 && logger.TotalErrorsLogged == 0; i++) { await Task.Delay(100); } // Same for after the non-listener pipe connection is closed Assert.Equal("Primary", await HttpClientSlim.GetStringAsync(address)); Assert.Equal("Secondary", await HttpClientSlim.GetStringAsync(address)); Assert.Equal("Primary", await HttpClientSlim.GetStringAsync(address)); await listenerSecondary.DisposeAsync(); await libuvThreadSecondary.StopAsync(TimeSpan.FromSeconds(5)); await listenerPrimary.DisposeAsync(); await libuvThreadPrimary.StopAsync(TimeSpan.FromSeconds(5)); Assert.Equal(1, logger.TotalErrorsLogged); var errorMessage = logger.Messages.First(m => m.LogLevel == LogLevel.Error); Assert.Equal(TestConstants.EOF, Assert.IsType <UvException>(errorMessage.Exception).StatusCode); }
public void ServerPipeListenForConnections() { const string pipeName = @"\\.\pipe\ServerPipeListenForConnections"; var loop = new UvLoopHandle(_logger); var serverListenPipe = new UvPipeHandle(_logger); loop.Init(_uv); serverListenPipe.Init(loop, (a, b) => { }, false); serverListenPipe.Bind(pipeName); serverListenPipe.Listen(128, async(backlog, status, error, state) => { var serverConnectionPipe = new UvPipeHandle(_logger); serverConnectionPipe.Init(loop, (a, b) => { }, true); try { serverListenPipe.Accept(serverConnectionPipe); } catch (Exception) { serverConnectionPipe.Dispose(); return; } var writeRequest = new UvWriteReq(_logger); writeRequest.DangerousInit(loop); await writeRequest.WriteAsync( serverConnectionPipe, new ReadOnlyBuffer(new byte[] { 1, 2, 3, 4 })); writeRequest.Dispose(); serverConnectionPipe.Dispose(); serverListenPipe.Dispose(); }, null); var worker = new Thread(() => { var loop2 = new UvLoopHandle(_logger); var clientConnectionPipe = new UvPipeHandle(_logger); var connect = new UvConnectRequest(_logger); loop2.Init(_uv); clientConnectionPipe.Init(loop2, (a, b) => { }, true); connect.DangerousInit(loop2); connect.Connect(clientConnectionPipe, pipeName, (handle, status, error, state) => { var buf = loop2.Libuv.buf_init(Marshal.AllocHGlobal(8192), 8192); connect.Dispose(); clientConnectionPipe.ReadStart( (handle2, cb, state2) => buf, (handle2, status2, state2) => { if (status2 == TestConstants.EOF) { clientConnectionPipe.Dispose(); } }, null); }, null); loop2.Run(); loop2.Dispose(); }); worker.Start(); loop.Run(); loop.Dispose(); worker.Join(); }
public Task StartAsync( string pipeName, ServerAddress address, KestrelThread thread, Func <Frame, Task> application) { ServerAddress = address; Thread = thread; Application = application; DispatchPipe = new UvPipeHandle(Log); var tcs = new TaskCompletionSource <int>(); Thread.Post(_ => { try { DispatchPipe.Init(Thread.Loop, true); var connect = new UvConnectRequest(Log); connect.Init(Thread.Loop); connect.Connect( DispatchPipe, pipeName, (connect2, status, error, state) => { connect.Dispose(); if (error != null) { tcs.SetException(error); return; } try { var ptr = Marshal.AllocHGlobal(4); var buf = Thread.Loop.Libuv.buf_init(ptr, 4); DispatchPipe.ReadStart( (_1, _2, _3) => buf, (_1, status2, state2) => { if (status2 < 0) { if (status2 != Constants.EOF) { Exception ex; Thread.Loop.Libuv.Check(status2, out ex); Log.LogError("DispatchPipe.ReadStart", ex); } DispatchPipe.Dispose(); Marshal.FreeHGlobal(ptr); return; } if (DispatchPipe.PendingCount() == 0) { return; } var acceptSocket = CreateAcceptSocket(); try { DispatchPipe.Accept(acceptSocket); } catch (UvException ex) { Log.LogError("DispatchPipe.Accept", ex); acceptSocket.Dispose(); return; } var connection = new Connection(this, acceptSocket); connection.Start(); }, null); tcs.SetResult(0); } catch (Exception ex) { DispatchPipe.Dispose(); tcs.SetException(ex); } }, null); } catch (Exception ex) { DispatchPipe.Dispose(); tcs.SetException(ex); } }, null); return(tcs.Task); }
public void ServerPipeListenForConnections() { var loop = new UvLoopHandle(_logger); var serverListenPipe = new UvPipeHandle(_logger); loop.Init(_uv); serverListenPipe.Init(loop, false); serverListenPipe.Bind(@"\\.\pipe\ServerPipeListenForConnections"); serverListenPipe.Listen(128, (_1, status, error, _2) => { var serverConnectionPipe = new UvPipeHandle(_logger); serverConnectionPipe.Init(loop, true); try { serverListenPipe.Accept(serverConnectionPipe); } catch (Exception) { serverConnectionPipe.Dispose(); return; } var writeRequest = new UvWriteReq(new KestrelTrace(new TestKestrelTrace())); writeRequest.Init(loop); var block = MemoryPoolBlock2.Create( new ArraySegment <byte>(new byte[] { 1, 2, 3, 4 }), dataPtr: IntPtr.Zero, pool: null, slab: null); var start = new MemoryPoolIterator2(block, 0); var end = new MemoryPoolIterator2(block, block.Data.Count); writeRequest.Write( serverConnectionPipe, start, end, 1, (_3, status2, error2, _4) => { writeRequest.Dispose(); serverConnectionPipe.Dispose(); serverListenPipe.Dispose(); block.Unpin(); }, null); }, null); var worker = new Thread(() => { var loop2 = new UvLoopHandle(_logger); var clientConnectionPipe = new UvPipeHandle(_logger); var connect = new UvConnectRequest(new KestrelTrace(new TestKestrelTrace())); loop2.Init(_uv); clientConnectionPipe.Init(loop2, true); connect.Init(loop2); connect.Connect(clientConnectionPipe, @"\\.\pipe\ServerPipeListenForConnections", (_1, status, error, _2) => { var buf = loop2.Libuv.buf_init(Marshal.AllocHGlobal(8192), 8192); connect.Dispose(); clientConnectionPipe.ReadStart( (_3, cb, _4) => buf, (_3, status2, _4) => { if (status2 == 0) { clientConnectionPipe.Dispose(); } }, null); }, null); loop2.Run(); loop2.Dispose(); }); worker.Start(); loop.Run(); loop.Dispose(); worker.Join(); }
public void ServerPipeDispatchConnections() { var pipeName = @"\\.\pipe\ServerPipeDispatchConnections" + Guid.NewGuid().ToString("n"); var loop = new UvLoopHandle(_logger); loop.Init(_uv); var serverConnectionPipe = default(UvPipeHandle); var serverConnectionPipeAcceptedEvent = new ManualResetEvent(false); var serverConnectionTcpDisposedEvent = new ManualResetEvent(false); var serverListenPipe = new UvPipeHandle(_logger); serverListenPipe.Init(loop, false); serverListenPipe.Bind(pipeName); serverListenPipe.Listen(128, (_1, status, error, _2) => { serverConnectionPipe = new UvPipeHandle(_logger); serverConnectionPipe.Init(loop, true); try { serverListenPipe.Accept(serverConnectionPipe); serverConnectionPipeAcceptedEvent.Set(); } catch (Exception ex) { Console.WriteLine(ex); serverConnectionPipe.Dispose(); serverConnectionPipe = null; } }, null); var serverListenTcp = new UvTcpHandle(_logger); serverListenTcp.Init(loop); var address = ServerAddress.FromUrl("http://localhost:54321/"); serverListenTcp.Bind(address); serverListenTcp.Listen(128, (_1, status, error, _2) => { var serverConnectionTcp = new UvTcpHandle(_logger); serverConnectionTcp.Init(loop); serverListenTcp.Accept(serverConnectionTcp); serverConnectionPipeAcceptedEvent.WaitOne(); var writeRequest = new UvWriteReq(new KestrelTrace(new TestKestrelTrace())); writeRequest.Init(loop); writeRequest.Write2( serverConnectionPipe, new ArraySegment <ArraySegment <byte> >(new ArraySegment <byte>[] { new ArraySegment <byte>(new byte[] { 1, 2, 3, 4 }) }), serverConnectionTcp, (_3, status2, error2, _4) => { writeRequest.Dispose(); serverConnectionTcp.Dispose(); serverConnectionTcpDisposedEvent.Set(); serverConnectionPipe.Dispose(); serverListenPipe.Dispose(); serverListenTcp.Dispose(); }, null); }, null); var worker = new Thread(() => { var loop2 = new UvLoopHandle(_logger); var clientConnectionPipe = new UvPipeHandle(_logger); var connect = new UvConnectRequest(new KestrelTrace(new TestKestrelTrace())); loop2.Init(_uv); clientConnectionPipe.Init(loop2, true); connect.Init(loop2); connect.Connect(clientConnectionPipe, pipeName, (_1, status, error, _2) => { connect.Dispose(); var buf = loop2.Libuv.buf_init(Marshal.AllocHGlobal(64), 64); serverConnectionTcpDisposedEvent.WaitOne(); clientConnectionPipe.ReadStart( (_3, cb, _4) => buf, (_3, status2, _4) => { if (status2 == 0) { clientConnectionPipe.Dispose(); return; } var clientConnectionTcp = new UvTcpHandle(_logger); clientConnectionTcp.Init(loop2); clientConnectionPipe.Accept(clientConnectionTcp); var buf2 = loop2.Libuv.buf_init(Marshal.AllocHGlobal(64), 64); clientConnectionTcp.ReadStart( (_5, cb, _6) => buf2, (_5, status3, _6) => { if (status3 == 0) { clientConnectionTcp.Dispose(); } }, null); }, null); }, null); loop2.Run(); loop2.Dispose(); }); var worker2 = new Thread(() => { try { serverConnectionPipeAcceptedEvent.WaitOne(); var socket = new Socket(SocketType.Stream, ProtocolType.IP); socket.Connect(IPAddress.Loopback, 54321); socket.Send(new byte[] { 6, 7, 8, 9 }); socket.Shutdown(SocketShutdown.Send); var cb = socket.Receive(new byte[64]); socket.Dispose(); } catch (Exception ex) { Console.WriteLine(ex); } }); worker.Start(); worker2.Start(); loop.Run(); loop.Dispose(); worker.Join(); worker2.Join(); }
public void ServerPipeListenForConnections() { var loop = new UvLoopHandle(_logger); var serverListenPipe = new UvPipeHandle(_logger); loop.Init(_uv); serverListenPipe.Init(loop, false); serverListenPipe.Bind(@"\\.\pipe\ServerPipeListenForConnections"); serverListenPipe.Listen(128, (_1, status, error, _2) => { var serverConnectionPipe = new UvPipeHandle(_logger); serverConnectionPipe.Init(loop, true); try { serverListenPipe.Accept(serverConnectionPipe); } catch (Exception) { serverConnectionPipe.Dispose(); return; } var writeRequest = new UvWriteReq(new KestrelTrace(new TestKestrelTrace())); writeRequest.Init(loop); writeRequest.Write( serverConnectionPipe, new ArraySegment <ArraySegment <byte> >(new ArraySegment <byte>[] { new ArraySegment <byte>(new byte[] { 1, 2, 3, 4 }) }), (_3, status2, error2, _4) => { writeRequest.Dispose(); serverConnectionPipe.Dispose(); serverListenPipe.Dispose(); }, null); }, null); var worker = new Thread(() => { var loop2 = new UvLoopHandle(_logger); var clientConnectionPipe = new UvPipeHandle(_logger); var connect = new UvConnectRequest(new KestrelTrace(new TestKestrelTrace())); loop2.Init(_uv); clientConnectionPipe.Init(loop2, true); connect.Init(loop2); connect.Connect(clientConnectionPipe, @"\\.\pipe\ServerPipeListenForConnections", (_1, status, error, _2) => { var buf = loop2.Libuv.buf_init(Marshal.AllocHGlobal(8192), 8192); connect.Dispose(); clientConnectionPipe.ReadStart( (_3, cb, _4) => buf, (_3, status2, errCode, error2, _4) => { if (status2 == 0) { clientConnectionPipe.Dispose(); } }, null); }, null); loop2.Run(); loop2.Dispose(); }); worker.Start(); loop.Run(); loop.Dispose(); worker.Join(); }
public void ServerPipeDispatchConnections() { var pipeName = @"\\.\pipe\ServerPipeDispatchConnections" + Guid.NewGuid().ToString("n"); var loop = new UvLoopHandle(_logger); loop.Init(_uv); var serverConnectionPipe = default(UvPipeHandle); var serverConnectionPipeAcceptedEvent = new ManualResetEvent(false); var serverConnectionTcpDisposedEvent = new ManualResetEvent(false); var serverListenPipe = new UvPipeHandle(_logger); serverListenPipe.Init(loop, (a, b) => { }, false); serverListenPipe.Bind(pipeName); serverListenPipe.Listen(128, (handle, status, error, state) => { serverConnectionPipe = new UvPipeHandle(_logger); serverConnectionPipe.Init(loop, (a, b) => { }, true); try { serverListenPipe.Accept(serverConnectionPipe); serverConnectionPipeAcceptedEvent.Set(); } catch (Exception ex) { Console.WriteLine(ex); serverConnectionPipe.Dispose(); serverConnectionPipe = null; } }, null); var serverListenTcp = new UvTcpHandle(_logger); serverListenTcp.Init(loop, (a, b) => { }); var address = ServerAddress.FromUrl($"http://127.0.0.1:0/"); serverListenTcp.Bind(address); var port = serverListenTcp.GetSockIPEndPoint().Port; serverListenTcp.Listen(128, (handle, status, error, state) => { var serverConnectionTcp = new UvTcpHandle(_logger); serverConnectionTcp.Init(loop, (a, b) => { }); serverListenTcp.Accept(serverConnectionTcp); serverConnectionPipeAcceptedEvent.WaitOne(); var writeRequest = new UvWriteReq(new KestrelTrace(new TestKestrelTrace())); writeRequest.Init(loop); writeRequest.Write2( serverConnectionPipe, new ArraySegment <ArraySegment <byte> >(new ArraySegment <byte>[] { new ArraySegment <byte>(new byte[] { 1, 2, 3, 4 }) }), serverConnectionTcp, (handle2, status2, error2, state2) => { writeRequest.Dispose(); serverConnectionTcp.Dispose(); serverConnectionTcpDisposedEvent.Set(); serverConnectionPipe.Dispose(); serverListenPipe.Dispose(); serverListenTcp.Dispose(); }, null); }, null); var worker = new Thread(() => { var loop2 = new UvLoopHandle(_logger); var clientConnectionPipe = new UvPipeHandle(_logger); var connect = new UvConnectRequest(new KestrelTrace(new TestKestrelTrace())); loop2.Init(_uv); clientConnectionPipe.Init(loop2, (a, b) => { }, true); connect.Init(loop2); connect.Connect(clientConnectionPipe, pipeName, (handle, status, error, state) => { connect.Dispose(); var buf = loop2.Libuv.buf_init(Marshal.AllocHGlobal(64), 64); serverConnectionTcpDisposedEvent.WaitOne(); clientConnectionPipe.ReadStart( (handle2, cb, state2) => buf, (handle2, status2, state2) => { if (status2 == Constants.EOF) { clientConnectionPipe.Dispose(); return; } var clientConnectionTcp = new UvTcpHandle(_logger); clientConnectionTcp.Init(loop2, (a, b) => { }); clientConnectionPipe.Accept(clientConnectionTcp); var buf2 = loop2.Libuv.buf_init(Marshal.AllocHGlobal(64), 64); clientConnectionTcp.ReadStart( (handle3, cb, state3) => buf2, (handle3, status3, state3) => { if (status3 == Constants.EOF) { clientConnectionTcp.Dispose(); } }, null); }, null); }, null); loop2.Run(); loop2.Dispose(); }); var worker2 = new Thread(() => { try { serverConnectionPipeAcceptedEvent.WaitOne(); var socket = TestConnection.CreateConnectedLoopbackSocket(port); socket.Send(new byte[] { 6, 7, 8, 9 }); socket.Shutdown(SocketShutdown.Send); var cb = socket.Receive(new byte[64]); socket.Dispose(); } catch (Exception ex) { Console.WriteLine(ex); } }); worker.Start(); worker2.Start(); loop.Run(); loop.Dispose(); worker.Join(); worker2.Join(); }
public void ServerPipeListenForConnections() { const string pipeName = @"\\.\pipe\ServerPipeListenForConnections"; var loop = new UvLoopHandle(_logger); var serverListenPipe = new UvPipeHandle(_logger); loop.Init(_uv); serverListenPipe.Init(loop, (a, b) => { }, false); serverListenPipe.Bind(pipeName); serverListenPipe.Listen(128, (backlog, status, error, state) => { var serverConnectionPipe = new UvPipeHandle(_logger); serverConnectionPipe.Init(loop, (a, b) => { }, true); try { serverListenPipe.Accept(serverConnectionPipe); } catch (Exception) { serverConnectionPipe.Dispose(); return; } var writeRequest = new UvWriteReq(new KestrelTrace(new TestKestrelTrace())); writeRequest.Init(loop); var pool = new MemoryPool(); var block = pool.Lease(); block.GetIterator().CopyFrom(new ArraySegment <byte>(new byte[] { 1, 2, 3, 4 })); var start = new MemoryPoolIterator(block, 0); var end = new MemoryPoolIterator(block, block.Data.Count); writeRequest.Write( serverConnectionPipe, start, end, 1, (handle, status2, error2, state2) => { writeRequest.Dispose(); serverConnectionPipe.Dispose(); serverListenPipe.Dispose(); pool.Return(block); pool.Dispose(); }, null); }, null); var worker = new Thread(() => { var loop2 = new UvLoopHandle(_logger); var clientConnectionPipe = new UvPipeHandle(_logger); var connect = new UvConnectRequest(new KestrelTrace(new TestKestrelTrace())); loop2.Init(_uv); clientConnectionPipe.Init(loop2, (a, b) => { }, true); connect.Init(loop2); connect.Connect(clientConnectionPipe, pipeName, (handle, status, error, state) => { var buf = loop2.Libuv.buf_init(Marshal.AllocHGlobal(8192), 8192); connect.Dispose(); clientConnectionPipe.ReadStart( (handle2, cb, state2) => buf, (handle2, status2, state2) => { if (status2 == Constants.EOF) { clientConnectionPipe.Dispose(); } }, null); }, null); loop2.Run(); loop2.Dispose(); }); worker.Start(); loop.Run(); loop.Dispose(); worker.Join(); }
public async Task NonListenerPipeConnectionsAreLoggedAndIgnored() { var libuv = new LibuvFunctions(); var endpoint = new IPEndPoint(IPAddress.Loopback, 0); var logger = new TestApplicationErrorLogger(); var transportContextPrimary = new TestLibuvTransportContext { Log = logger }; var transportContextSecondary = new TestLibuvTransportContext(); var pipeName = (libuv.IsWindows ? @"\\.\pipe\kestrel_" : "/tmp/kestrel_") + Guid.NewGuid().ToString("n"); var pipeMessage = Guid.NewGuid().ToByteArray(); // Start primary listener var libuvThreadPrimary = new LibuvThread(libuv, transportContextPrimary); await libuvThreadPrimary.StartAsync(); var listenerPrimary = new ListenerPrimary(transportContextPrimary); await listenerPrimary.StartAsync(pipeName, pipeMessage, endpoint, libuvThreadPrimary); var address = GetUri(listenerPrimary.EndPoint); // Add secondary listener var libuvThreadSecondary = new LibuvThread(libuv, transportContextSecondary); await libuvThreadSecondary.StartAsync(); var listenerSecondary = new ListenerSecondary(transportContextSecondary); await listenerSecondary.StartAsync(pipeName, pipeMessage, endpoint, libuvThreadSecondary); // TCP Connections get round-robined var primary = await WaitForSecondaryListener(address, listenerPrimary, listenerSecondary); // Make sure the pending accept get yields using (var socket = await HttpClientSlim.GetSocket(address)) { await(await primary.DefaultTimeout()).DisposeAsync(); } // Create a pipe connection and keep it open without sending any data var connectTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var connectionTrace = new TestApplicationErrorLogger(); var pipe = new UvPipeHandle(connectionTrace); libuvThreadPrimary.Post(_ => { var connectReq = new UvConnectRequest(connectionTrace); pipe.Init(libuvThreadPrimary.Loop, libuvThreadPrimary.QueueCloseHandle); connectReq.Init(libuvThreadPrimary); connectReq.Connect( pipe, pipeName, (req, status, ex, __) => { req.Dispose(); if (ex != null) { connectTcs.SetException(ex); } else { connectTcs.SetResult(); } }, null); }, (object)null); await connectTcs.Task; // TCP connections will still get round-robined between only the two listeners await AssertRoundRobin(address, listenerPrimary, listenerSecondary, listenerPrimary); await libuvThreadPrimary.PostAsync(_ => pipe.Dispose(), (object)null); // Wait up to 10 seconds for error to be logged for (var i = 0; i < 10 && logger.TotalErrorsLogged == 0; i++) { await Task.Delay(100); } // Same for after the non-listener pipe connection is closed await AssertRoundRobin(address, listenerPrimary, listenerSecondary, listenerPrimary); await listenerSecondary.DisposeAsync(); await libuvThreadSecondary.StopAsync(TimeSpan.FromSeconds(5)); await listenerPrimary.DisposeAsync(); await libuvThreadPrimary.StopAsync(TimeSpan.FromSeconds(5)); Assert.Equal(0, logger.TotalErrorsLogged); var logMessage = logger.Messages.Single(m => m.Message == "An internal pipe was opened unexpectedly."); Assert.Equal(LogLevel.Debug, logMessage.LogLevel); }