private async Task OnConnection(IPipeConnection connection)
        {
            using (connection)
            {
                WebSocketConnection socket = null;
                try
                {
                    WriteStatus(ConnectionType.Server, "Connected");

                    WriteStatus(ConnectionType.Server, "Parsing http request...");
                    var request = await ParseHttpRequest(connection.Input);

                    try
                    {
                        WriteStatus(ConnectionType.Server, "Identifying protocol...");
                        socket = GetProtocol(connection, ref request);
                        WriteStatus(ConnectionType.Server, $"Protocol: {WebSocketProtocol.Name}");
                        WriteStatus(ConnectionType.Server, "Authenticating...");
                        if (!await OnAuthenticateAsync(socket, ref request.Headers))
                        {
                            throw new InvalidOperationException("Authentication refused");
                        }
                        WriteStatus(ConnectionType.Server, "Completing handshake...");
                        await WebSocketProtocol.CompleteServerHandshakeAsync(ref request, socket);
                    }
                    finally
                    {
                        request.Dispose(); // can't use "ref request" or "ref headers" otherwise
                    }
                    WriteStatus(ConnectionType.Server, "Handshake complete hook...");
                    await OnHandshakeCompleteAsync(socket);

                    connections.TryAdd(socket, socket);
                    WriteStatus(ConnectionType.Server, "Processing incoming frames...");
                    await socket.ProcessIncomingFramesAsync(this);

                    WriteStatus(ConnectionType.Server, "Exiting...");
                    await socket.CloseAsync();
                }
                catch (Exception ex)
                {// meh, bye bye broken connection
                    try { socket?.Dispose(); } catch { }
                    WriteStatus(ConnectionType.Server, ex.StackTrace);
                    WriteStatus(ConnectionType.Server, ex.GetType().Name);
                    WriteStatus(ConnectionType.Server, ex.Message);
                }
                finally
                {
                    WebSocketConnection tmp;
                    if (socket != null)
                    {
                        connections.TryRemove(socket, out tmp);
                    }
                    try { connection.Output.Complete(); } catch { }
                    try { connection.Input.Complete(); } catch { }
                }
            }
        }
 private async void SendCloseWhenOutputCompleted()
 {
     await _output.Reading;
     await _webSocket.CloseAsync();
 }