module Util.Socket
( connectSocket
, serverSocket
, acceptSocket
, closeSock
, Socket()
) where
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as CS
import Data.Word
import Network.Socket hiding (recv, recvFrom, send, sendTo)
import Util.IOExtra
connectSocket :: BS.ByteString -> Word16 -> IO Socket
connectSocket hostName portNumber = do
(sock, sa) <- createSocket hostName (Just portNumber)
handleAll (\e -> closeSock sock >> throwM e) $ do
setSocketOption sock NoDelay 1
connect sock sa
return sock
serverSocket :: BS.ByteString -> IO (Socket, Word16)
serverSocket hostName = do
(sock, sa) <- createSocket hostName Nothing
handleAll (\e -> closeSock sock >> throwM e) $ do
bind sock sa
listen sock 5
port <- socketPort sock
return (sock, fromIntegral port)
acceptSocket :: Socket -> IO Socket
acceptSocket sock = do
(sock', _sa) <- accept sock
handleAll (\e -> closeSock sock' >> throwM e) $ do
setSocketOption sock' NoDelay 1
return sock'
closeSock :: Socket -> IO ()
closeSock = close
createSocket :: MonadIO m
=> BS.ByteString
-> Maybe Word16
-> m (Socket, SockAddr)
createSocket hostName portNumber =
liftIO $ do
ai <- addrInfo
sock <- socket (addrFamily ai) (addrSocketType ai) (addrProtocol ai)
return (sock, addrAddress ai)
where
addrInfo = do
let hints = defaultHints { addrFlags = [ AI_CANONNAME
, AI_NUMERICSERV
, AI_ADDRCONFIG
]
, addrFamily = AF_INET
, addrSocketType = Stream
}
(ai : _) <- getAddrInfo (Just hints)
(Just (CS.unpack hostName))
(show <$> portNumber)
return ai