Exemple #1
0
        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()
        {
            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,
                    ReadableBuffer.Create(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 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 transportContextPrimary = new TestLibuvTransportContext()
            {
                Log = new LibuvTrace(logger)
            };

            transportContextPrimary.ConnectionHandler = new ConnectionHandler <HttpContext>(
                listenOptions, serviceContextPrimary, new DummyApplication(c => c.Response.WriteAsync("Primary")));

            var serviceContextSecondary = new TestServiceContext
            {
                DateHeaderValueManager = serviceContextPrimary.DateHeaderValueManager,
                ServerOptions          = serviceContextPrimary.ServerOptions,
                ThreadPool             = serviceContextPrimary.ThreadPool,
                HttpParserFactory      = serviceContextPrimary.HttpParserFactory,
            };
            var transportContextSecondary = new TestLibuvTransportContext();

            transportContextSecondary.ConnectionHandler = new ConnectionHandler <HttpContext>(
                listenOptions, serviceContextSecondary, new DummyApplication(c => c.Response.WriteAsync("Secondary")));

            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>();
            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(1));

            await listenerPrimary.DisposeAsync();

            await libuvThreadPrimary.StopAsync(TimeSpan.FromSeconds(1));

            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 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 endPoint = new IPEndPoint(IPAddress.Loopback, 0);

            serverListenTcp.Bind(endPoint);
            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(_logger);
                writeRequest.DangerousInit(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(_logger);

                loop2.Init(_uv);
                clientConnectionPipe.Init(loop2, (a, b) => { }, true);
                connect.DangerousInit(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 == TestConstants.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 == TestConstants.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();
        }
Exemple #5
0
        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();
        }
Exemple #6
0
        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();
        }
Exemple #7
0
        public async Task NonListenerPipeConnectionsAreLoggedAndIgnored()
        {
            var libuv    = new LibuvFunctions();
            var endpoint = new IPEndPoint(IPAddress.Loopback, 0);
            var logger   = new TestApplicationErrorLogger();

            var transportContextPrimary = new TestLibuvTransportContext {
                Log = new LibuvTrace(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 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);
            }, (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);
        }
Exemple #8
0
        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();
        }