1module Network.Socket.Handle where
2
3import qualified GHC.IO.Device (IODeviceType(Stream))
4import GHC.IO.Handle.FD (fdToHandle')
5import System.IO (IOMode(..), Handle, BufferMode(..), hSetBuffering)
6
7import Network.Socket.Types
8
9-- | Turns a Socket into an 'Handle'. By default, the new handle is
10-- unbuffered. Use 'System.IO.hSetBuffering' to change the buffering.
11--
12-- Note that since a 'Handle' is automatically closed by a finalizer
13-- when it is no longer referenced, you should avoid doing any more
14-- operations on the 'Socket' after calling 'socketToHandle'.  To
15-- close the 'Socket' after 'socketToHandle', call 'System.IO.hClose'
16-- on the 'Handle'.
17--
18-- Caveat 'Handle' is not recommended for network programming in
19-- Haskell, e.g. merely performing 'hClose' on a TCP socket won't
20-- cooperate with peer's 'gracefulClose', i.e. proper shutdown
21-- sequence with appropriate handshakes specified by the protocol.
22
23socketToHandle :: Socket -> IOMode -> IO Handle
24socketToHandle s mode = invalidateSocket s err $ \oldfd -> do
25    h <- fdToHandle' oldfd (Just GHC.IO.Device.Stream) True (show s) mode True{-bin-}
26    hSetBuffering h NoBuffering
27    return h
28  where
29    err _ = ioError $ userError $ "socketToHandle: socket is no longer valid"
30