Some refactoring.

This commit is contained in:
Abhinav Sarkar 2015-09-10 02:55:29 +05:30
parent 5dc9a2cf14
commit 40abe5dd15
4 changed files with 23 additions and 20 deletions

View File

@ -1,8 +1,9 @@
module Main where module Main where
import Link.Server
import System.Environment (getArgs) import System.Environment (getArgs)
import Link.Server
main :: IO () main :: IO ()
main = do main = do
port <- fmap (read . (!! 0)) getArgs port <- fmap (read . (!! 0)) getArgs

View File

@ -26,11 +26,14 @@ race ioa iob = do
bracket (forkFinally (fmap Right iob) (putMVar m)) killThread $ \_ -> do bracket (forkFinally (fmap Right iob) (putMVar m)) killThread $ \_ -> do
r <- readMVar m r <- readMVar m
case r of case r of
Left e -> throwIO e Left e -> throwIO e
Right a -> return a Right a -> return a
sendMessage :: Message -> Client -> IO () sendMessage :: Client -> Message -> IO ()
sendMessage message Client {..} = writeChan clientChan message sendMessage Client {..} = writeChan clientChan
sendResponse :: Client -> Message -> IO ()
sendResponse Client {..} = printToHandle clientHandle . formatMessage
runClient :: Server -> Client -> IO () runClient :: Server -> Client -> IO ()
runClient Server {..} client@Client {..} = do runClient Server {..} client@Client {..} = do
@ -42,7 +45,7 @@ runClient Server {..} client@Client {..} = do
pingDelayMicros = pingDelay * 1000 * 1000 pingDelayMicros = pingDelay * 1000 * 1000
ping clientAlive = do ping clientAlive = do
sendMessage Ping client sendMessage client Ping
threadDelay pingDelayMicros threadDelay pingDelayMicros
now <- getCurrentTime now <- getCurrentTime
pongTime <- readMVar clientPongTime pongTime <- readMVar clientPongTime
@ -60,12 +63,12 @@ runClient Server {..} client@Client {..} = do
Left (e :: SomeException) -> printf "Exception: %s\n" (show e) Left (e :: SomeException) -> printf "Exception: %s\n" (show e)
Right g -> case g of Right g -> case g of
Nothing -> run clientAlive Nothing -> run clientAlive
Just cm -> do Just cm -> do
case cm of case cm of
Left mcommand -> case mcommand of Left mcommand -> case mcommand of
Nothing -> printf "Could not parse command\n" Nothing -> printf "Could not parse command\n"
Just command -> handleCommand command Just command -> handleCommand command
Right message -> sendResponse message Right message -> sendResponse client message
run clientAlive run clientAlive
readCommand = do readCommand = do
@ -78,10 +81,8 @@ runClient Server {..} client@Client {..} = do
handleCommand (PrivMsg user msg) = handleCommand (PrivMsg user msg) =
withMVar serverUsers $ \clientMap -> withMVar serverUsers $ \clientMap ->
case Map.lookup user clientMap of case Map.lookup user clientMap of
Nothing -> sendResponse $ NoSuchUser (userName user) Nothing -> sendResponse client $ NoSuchUser (userName user)
Just client' -> sendMessage (PrivMsg clientUser msg) client' Just client' -> sendMessage client' $ PrivMsg clientUser msg
handleCommand Pong = do handleCommand Pong = do
now <- getCurrentTime now <- getCurrentTime
void $ swapMVar clientPongTime now void $ swapMVar clientPongTime now
sendResponse = printToHandle clientHandle . formatMessage

View File

@ -1,7 +1,7 @@
module Link.Server where module Link.Server where
import Control.Concurrent
import Control.Exception hiding (handle) import Control.Exception hiding (handle)
import Control.Concurrent hiding (forkFinally)
import Control.Monad (forever) import Control.Monad (forever)
import Data.Time (getCurrentTime) import Data.Time (getCurrentTime)
import Network (withSocketsDo, listenOn, accept, PortID(..)) import Network (withSocketsDo, listenOn, accept, PortID(..))
@ -42,11 +42,11 @@ connectClient server handle = do
let user = User name let user = User name
ok <- checkAddClient server user handle ok <- checkAddClient server user handle
case ok of case ok of
Nothing -> do Nothing -> do
printToHandle handle $ formatMessage (NameInUse name) printToHandle handle $ formatMessage (NameInUse name)
readName readName
Just client -> do Just client -> do
printToHandle handle $ formatMessage (Connected name) sendResponse client $ Connected name
runClient server client `finally` removeClient server user runClient server client `finally` removeClient server user
checkAddClient :: Server -> User -> Handle -> IO (Maybe Client) checkAddClient :: Server -> User -> Handle -> IO (Maybe Client)
@ -55,13 +55,13 @@ checkAddClient Server {..} user@User {..} handle =
if Map.member user clientMap if Map.member user clientMap
then return (clientMap, Nothing) then return (clientMap, Nothing)
else do else do
clientChan <- newChan clientChan <- newChan
now <- newMVar =<< getCurrentTime now <- getCurrentTime
let client = Client user handle clientChan now clientPongTime <- newMVar now
let client = Client user handle clientChan clientPongTime
printf "New user connected: %s\n" userName printf "New user connected: %s\n" userName
return (Map.insert user client clientMap, Just client) return (Map.insert user client clientMap, Just client)
removeClient :: Server -> User -> IO () removeClient :: Server -> User -> IO ()
removeClient Server {..} user = removeClient Server {..} user =
modifyMVar_ serverUsers $ \clientMap -> modifyMVar_ serverUsers $ return . Map.delete user
return $ Map.delete user clientMap

View File

@ -1,8 +1,9 @@
module Link.Types where module Link.Types where
import Control.Concurrent (MVar, Chan)
import Data.Time (UTCTime) import Data.Time (UTCTime)
import System.IO (Handle) import System.IO (Handle)
import Control.Concurrent (MVar, Chan)
import qualified Data.Map as Map import qualified Data.Map as Map
type UserName = String type UserName = String