salvia-0.0.4: src/Network/Salvia/Core/Network.hs
module Network.Salvia.Core.Network where
import Control.Concurrent (forkIO)
-- import Control.Exception (try)
import Control.Monad
import Network.Socket
import System.IO
-------- application independent networking -----------------------------------
type Server a =
Handle
-> SockAddr
-> IO a
{-
Start a listening TCP server on the specified address/port combination and
handle every connection with a custom handler.
-}
server :: HostAddress -> PortNumber -> Int -> Server a -> IO ()
server addr port backlog handler = do
sock <- socket AF_INET Stream 0
setSocketOption sock ReuseAddr 1
bindSocket sock $ SockAddrInet port addr
listen sock backlog
acceptLoop sock handler
{-
Accept connections on the listening socket and pass execution to the
application specific connection handler.
-}
acceptLoop :: Socket -> Server s -> IO ()
acceptLoop sock handler = do
forever $ do
(sock', addr) <- accept sock
forkIO $ do
handle <- socketToHandle sock' ReadWriteMode
-- TODO: Using NoBuffering here may crash the entire program (GHC
-- runtime?) when processing more requests than just a few:
hSetBuffering handle (BlockBuffering (Just (64*1024)))
handler handle addr
-- We can probably just ignore exceptions from hClose, but this for the
-- moment I am interested whether this even happens.
hClose handle
-- e <- try (hClose handle)
-- case e of
-- Left ex -> putStrLn ("Failure during hClose: " ++ show (ex :: IOException))
-- Right _ -> return ()
putStrLn "quiting"