wsEchoClient ::
    SocketConfig ->
    Managed (View SocketComms, Controller SocketComms)
wsEchoClient c = join $ managed $ \k -> do
    ref <- newIORef Nothing
    (oV, iV, sealV) <- spawn' unbounded
    (oC, iC, sealC) <- spawn' unbounded
    aV <- async $ do
        runEffect $
            fromInput iV >->
            Pipes.chain (\x -> case x of
                ServerReady -> do
                    aClient <- async $ WS.runClient (c^.cHost) (c^.cPort) "/" echoClient
                    writeIORef ref (Just aClient)
                    (void . atomically . send oC) ClientReady
                ServerClosed -> do
                    F.mapM_ cancel =<< readIORef ref
                    (void . atomically . send oC) ClientClosed
                _ -> return ()) >->
            forever await
        atomically sealV
        atomically sealC

    res <- k (return
       ( asSink (void . atomically . send oV)
       , asInput iC))
        <* atomically sealV
        <* atomically sealC
    cancel aV
    return res
wsEchoClient ::
    SocketConfig ->
    Managed (View SocketComms, Controller SocketComms)
wsEchoClient c = join $ managed $ \k -> do
    ref <- newIORef Nothing
    (oV, iV, sealV) <- spawn' unbounded
    (oC, iC, sealC) <- spawn' unbounded
    aV <- async $ do
        runEffect $
            fromInput iV >->
            Pipes.chain (\x -> case x of
                ServerReady -> do
                    aClient <- async $ WS.runClient (c^.cHost) (c^.cPort) "/" echoClient
                    writeIORef ref (Just aClient)
                    (void . atomically . send oC) ClientReady
                ServerClosed -> do
                    F.mapM_ cancel =<< readIORef ref
                    (void . atomically . send oC) ClientClosed
                _ -> return ()) >->
            forever await
        atomically sealV
        atomically sealC

    res <- k (return
       ( asSink (void . atomically . send oV)
       , asInput iC))
        <* atomically sealV
        <* atomically sealC
    cancel aV
    return res
wsEchoClient c = join $ managed $ \k -> do
    ref <- newIORef Nothing
    (oV, iV, sealV) <- spawn' unbounded
    (oC, iC, sealC) <- spawn' unbounded
    aV <- async $ do
        runEffect $
            fromInput iV >->
            Pipes.chain (\x -> case x of
                ServerReady -> do
                    aClient <- async $ WS.runClient (c^.cHost) (c^.cPort) "/" echoClient
                    writeIORef ref (Just aClient)
                    (void . atomically . send oC) ClientReady
                ServerClosed -> do
                    F.mapM_ cancel =<< readIORef ref
                    (void . atomically . send oC) ClientClosed
                _ -> return ()) >->
            forever await
        atomically sealV
        atomically sealC

    res <- k (return
       ( asSink (void . atomically . send oV)
       , asInput iC))
        <* atomically sealV
        <* atomically sealC
    cancel aV
    return res