1804
+ − 1
{-# LANGUAGE PatternSignatures #-}
+ − 2
module ClientIO where
+ − 3
+ − 4
import qualified Control.Exception
+ − 5
import Control.Concurrent.Chan
+ − 6
import Control.Monad
+ − 7
import System.IO
+ − 8
----------------
+ − 9
import CoreTypes
+ − 10
2001
+ − 11
listenLoop :: Handle -> Int -> [String] -> Chan CoreMessage -> Int -> IO ()
+ − 12
listenLoop handle linesNumber buf chan clientID = do
1804
+ − 13
str <- hGetLine handle
2001
+ − 14
if (linesNumber > 50) || (length str > 450) then
+ − 15
writeChan chan $ ClientMessage (clientID, ["QUIT", "Protocol violation"])
1804
+ − 16
else
2001
+ − 17
if str == "" then do
+ − 18
writeChan chan $ ClientMessage (clientID, buf)
+ − 19
listenLoop handle 0 [] chan clientID
+ − 20
else
+ − 21
listenLoop handle (linesNumber + 1) (buf ++ [str]) chan clientID
1804
+ − 22
+ − 23
clientRecvLoop :: Handle -> Chan CoreMessage -> Int -> IO ()
+ − 24
clientRecvLoop handle chan clientID =
2001
+ − 25
listenLoop handle 0 [] chan clientID
1804
+ − 26
`catch` (\e -> (clientOff $ show e) >> return ())
+ − 27
where clientOff msg = writeChan chan $ ClientMessage (clientID, ["QUIT", msg]) -- if the client disconnects, we perform as if it sent QUIT message
+ − 28
+ − 29
clientSendLoop :: Handle -> Chan CoreMessage -> Chan [String] -> Int -> IO()
+ − 30
clientSendLoop handle coreChan chan clientID = do
+ − 31
answer <- readChan chan
+ − 32
doClose <- Control.Exception.handle
+ − 33
(\(e :: Control.Exception.Exception) -> if isQuit answer then return True else sendQuit e >> return False) $ do
+ − 34
forM_ answer (\str -> hPutStrLn handle str)
+ − 35
hPutStrLn handle ""
+ − 36
hFlush handle
+ − 37
return $ isQuit answer
+ − 38
+ − 39
if doClose then
+ − 40
Control.Exception.handle (\(_ :: Control.Exception.Exception) -> putStrLn "error on hClose") $ hClose handle
+ − 41
else
+ − 42
clientSendLoop handle coreChan chan clientID
+ − 43
+ − 44
where
+ − 45
sendQuit e = writeChan coreChan $ ClientMessage (clientID, ["QUIT", show e])
+ − 46
isQuit answer = head answer == "BYE"