From f2f5def1d782d8409c8d35b3a13d0f978a25a995 Mon Sep 17 00:00:00 2001
From: Jens Nolte <git@queezle.net>
Date: Sun, 5 Sep 2021 22:51:41 +0200
Subject: [PATCH] Add send- and receive thread

---
 quasar-wayland.cabal         |  2 +-
 src/Quasar/Wayland/Client.hs | 39 +++++++++++++++++++++++++++++++++---
 2 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/quasar-wayland.cabal b/quasar-wayland.cabal
index 77ff807..63d666c 100644
--- a/quasar-wayland.cabal
+++ b/quasar-wayland.cabal
@@ -98,7 +98,7 @@ library
     template-haskell,
     --unix,
     --unordered-containers,
-    --stm,
+    stm,
     xml,
     -- required for record-dot-preprocessor
     record-dot-preprocessor,
diff --git a/src/Quasar/Wayland/Client.hs b/src/Quasar/Wayland/Client.hs
index 3d055a8..0a3d3c3 100644
--- a/src/Quasar/Wayland/Client.hs
+++ b/src/Quasar/Wayland/Client.hs
@@ -3,17 +3,21 @@ module Quasar.Wayland.Client (
   newWaylandClient,
 ) where
 
+import Control.Concurrent.STM
 import Control.Monad.Catch
-import Network.Socket qualified as Socket
 import Network.Socket (Socket)
+import Network.Socket qualified as Socket
+import Network.Socket.ByteString qualified as Socket
 import Quasar
 import Quasar.Prelude
+import Quasar.Wayland.Protocol
 import System.Environment (getEnv, lookupEnv)
 import System.FilePath ((</>), isRelative)
 import Text.Read (readEither)
 
 
 data WaylandClient = WaylandClient {
+  protocolStateVar :: TVar ProtocolState,
   socket :: Socket,
   resourceManager :: ResourceManager
 }
@@ -26,14 +30,43 @@ instance IsDisposable WaylandClient where
 
 newWaylandClient :: MonadResourceManager m => Socket -> m WaylandClient
 newWaylandClient socket = do
+  protocolStateVar <- liftIO $ newTVarIO initialProtocolState
   resourceManager <- newResourceManager
+
   onResourceManager resourceManager do
-    registerDisposeAction (pure () <$ Socket.close socket)
-    pure WaylandClient {
+    let client = WaylandClient {
+      protocolStateVar,
       socket,
       resourceManager
     }
 
+    registerDisposeAction $ closeWaylandClient client
+
+    runUnlimitedAsync do
+      async $ liftIO $ waylandClientSendThread client
+      async $ liftIO $ waylandClientReceiveThread client
+
+    pure client
+
+waylandClientSendThread :: WaylandClient -> IO ()
+waylandClientSendThread client = forever do
+  undefined
+
+waylandClientReceiveThread :: WaylandClient -> IO ()
+waylandClientReceiveThread client = forever do
+  bytes <- Socket.recv client.socket 4096
+  traceIO $ "Received data"
+  atomically $ modifyTVar client.protocolStateVar $ feedInput bytes
+
+  state <- atomically $ readTVar client.protocolStateVar
+  traceIO $ show state.bytesReceived
+
+closeWaylandClient :: WaylandClient -> IO (Awaitable ())
+closeWaylandClient client = isDisposed <$> forkTask do
+  -- gracefulClose may fail but guarantees that the socket is deallocated
+  Socket.gracefulClose client.socket 2000 `catch` \(_ :: SomeException) -> pure ()
+
+
 connectWaylandClient :: MonadResourceManager m => m WaylandClient
 connectWaylandClient = mask_ do
   socket <- liftIO connectWaylandSocket
-- 
GitLab