module System.Miniplex.Source (
Source,
attach,
read,
getMsgs,
detach,
withSource
) where
import System.Miniplex.Sekrit
import Prelude hiding (read)
import Control.Exception
import Control.Monad
import Control.Monad.Reader ()
import Data.Typeable
import Network.Socket
import System.IO.Unsafe
newtype Source = Source {
sock :: Socket
} deriving (Typeable)
attach :: String -> IO Source
attach what = do
n <- pathFromTag "System.Miniplex.Source.attach" what
bracketOnError
(socket AF_UNIX Stream 0)
sClose
$ \s -> do
closeOnExec s
connect s (SockAddrUnix n)
shutdown s ShutdownSend
return $ Source {sock = s}
read :: Source -> IO String
read so = do
n <- liftM intFromBytes $ reallyRecv s 4
reallyRecv s n
where
s = sock so
getMsgs :: Source -> IO [String]
getMsgs so = unsafeInterleaveIO . handle (\_ -> detach so >> return []) $
liftM2 (liftM2 (:)) read getMsgs so
detach :: Source -> IO ()
detach so = do
sClose (sock so)
withSource :: String -> (Source -> IO a) -> IO a
withSource tag f = block $ do
so <- attach tag
unblock (f so) `finally` detach so