packages feed

salvia-0.0.5: src/Network/Salvia/Core/Network.hs

module Network.Salvia.Core.Network where

import Control.Concurrent (forkIO)
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"