--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/netserver/Miscutils.hs Fri Apr 18 18:06:17 2008 +0000
@@ -0,0 +1,27 @@
+module Miscutils where
+
+import IO
+import System.IO
+import Control.Concurrent
+import Control.Concurrent.STM
+import Control.Exception (finally)
+
+sendMsg :: Handle -> String -> IO()
+sendMsg clientHandle str = finally (return ()) (hPutStrLn clientHandle str >> hFlush clientHandle) -- catch exception when client tries to send to other
+
+sendAll :: [Handle] -> String -> IO[()]
+sendAll clientsList str = mapM (\x -> sendMsg x str) clientsList
+
+sendOthers :: [Handle] -> Handle -> String -> IO[()]
+sendOthers clientsList clientHandle str = sendAll (filter (/= clientHandle) clientsList) str
+
+extractCmd :: String -> (String, [String])
+extractCmd str = if ws == [] then ("", []) else (head ws, tail ws)
+ where ws = words str
+
+manipState :: TVar[a] -> ([a] -> [a]) -> IO()
+manipState state op =
+ atomically $ do
+ ls <- readTVar state
+ writeTVar state $ op ls
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/netserver/hwserv.hs Fri Apr 18 18:06:17 2008 +0000
@@ -0,0 +1,74 @@
+module Main where
+
+import Network
+import IO
+import System.IO
+import Control.Concurrent
+import Control.Concurrent.STM
+import Control.Exception (finally)
+import Miscutils
+
+data ClientInfo =
+ ClientInfo
+ {
+ handle :: Handle,
+ nick :: String,
+ game :: String,
+ isMaster :: Bool
+ }
+
+data RoomInfo =
+ RoomInfo
+ {
+ name :: String,
+ password :: String
+ }
+
+
+handleCmd :: Handle -> TVar[ClientInfo] -> TVar[RoomInfo] -> (String, [String]) -> IO()
+handleCmd clientHandle clientsList roomsList ("SAY", param) = do
+ ls <- atomically(readTVar clientsList)
+ sendOthers (map (\x -> handle x) ls) clientHandle (concat param)
+ return ()
+
+handleCmd clientHandle clientsList roomsList ("CREATE", [roomname]) = do
+ manipState roomsList (\x -> (RoomInfo roomname ""):x)
+ manipState clientsList (\x -> map (\xc -> if (clientHandle == handle xc) then xc{isMaster = True, game = roomname} else xc) x)
+ sendMsg clientHandle ("JOINED " ++ roomname)
+
+handleCmd clientHandle clientsList roomsList ("LIST", []) = do
+ rl <- atomically $ readTVar roomsList
+ sendMsg clientHandle (unlines $ map (\x -> name x) rl)
+
+handleCmd clientHandle _ _ ("PING", _) = sendMsg clientHandle "PONG"
+
+handleCmd clientHandle _ _ (_, _) = sendMsg clientHandle "Unknown cmd or bad syntax"
+
+
+clientLoop :: Handle -> TVar[ClientInfo] -> TVar[RoomInfo] -> IO()
+clientLoop clientHandle clientsList roomsList = do
+ cline <- hGetLine clientHandle
+ let (cmd, params) = extractCmd cline
+ handleCmd clientHandle clientsList roomsList (cmd, params)
+ if cmd /= "QUIT" then clientLoop clientHandle clientsList roomsList else return ()
+
+
+main = do
+ clientsList <- atomically $ newTVar[]
+ roomsList <- atomically $ newTVar[]
+ bracket
+ (listenOn $ PortNumber 46631)
+ (sClose)
+ (loop clientsList roomsList)
+ where
+ loop clist rlist sock = accept sock >>= addClient clist rlist >> loop clist rlist sock
+
+ addClient clist rlist (chandle, hostname, port) = do
+ putStrLn $ "Client connected: " ++ show hostname
+ hSetBuffering chandle LineBuffering
+ manipState clist (\x -> (ClientInfo chandle "" "" False):x) -- add client to list
+ forkIO $ finally
+ (clientLoop chandle clist rlist)
+ (do
+ manipState clist (\x -> filter (\x -> chandle /= handle x) x) -- remove client from list
+ hClose chandle)