53 lines
1.5 KiB
Haskell
53 lines
1.5 KiB
Haskell
module WebSocket (broadcast, initMVarState, runWebSocketServer, ServerState, Client) where
|
|
|
|
import ClassyPrelude
|
|
import Network.WebSockets qualified as WS
|
|
|
|
type Client = (Text, WS.Connection)
|
|
|
|
type ServerState = [Client]
|
|
|
|
addClient :: Client -> ServerState -> ServerState
|
|
addClient client clients = client : clients
|
|
|
|
removeClient :: Client -> ServerState -> ServerState
|
|
removeClient client = filter ((/= fst client) . fst)
|
|
|
|
newServerState :: ServerState
|
|
newServerState = []
|
|
|
|
broadcast :: Text -> ServerState -> IO ()
|
|
broadcast message clients = do
|
|
putStrLn message
|
|
forM_ clients $ \(_, conn) -> WS.sendTextData conn message
|
|
|
|
initMVarState :: IO (MVar ServerState)
|
|
initMVarState = newMVar newServerState
|
|
|
|
runWebSocketServer :: MVar ServerState -> IO ()
|
|
runWebSocketServer state = do
|
|
WS.runServer "127.0.0.1" 9160 $ webSocketApplication state
|
|
|
|
webSocketApplication :: MVar ServerState -> WS.ServerApp
|
|
webSocketApplication state pending = do
|
|
putStrLn "pending request"
|
|
conn <- WS.acceptRequest pending
|
|
WS.withPingThread conn 30 (return ()) $ do
|
|
msg <- WS.receiveData conn
|
|
putStrLn msg
|
|
let client = ("hall", conn)
|
|
flip finally (disconnect client) $ do
|
|
modifyMVar_ state $ \s -> do
|
|
let s' = addClient client s
|
|
return s'
|
|
forever $ do
|
|
currentMsg <- WS.receiveData conn
|
|
putStrLn currentMsg
|
|
where
|
|
disconnect client = do
|
|
putStrLn "disconnect"
|
|
modifyMVar state $ \s ->
|
|
let s' = removeClient client s
|
|
in return
|
|
(s', s')
|