Some refactoring.
This commit is contained in:
parent
5dc9a2cf14
commit
40abe5dd15
@ -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
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user