{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE CPP #-} module Network.Run.Core ( runClient , resolve , openServerSocket ) where import qualified Control.Exception as E import Control.Monad (when) import Network.Socket runClient :: SocketType -> String -> String -> (Socket -> SockAddr -> IO a) -> IO a runClient socketType host port client = withSocketsDo $ do addr <- resolve socketType (Just host) port False let sockAddr = addrAddress addr #if MIN_VERSION_network(3,1,1) E.bracket (open addr) (\sock -> gracefulClose sock 5000) (\sock -> client sock sockAddr) #else E.bracket (open addr) close $ \sock -> client sock sockAddr #endif where open addr = do sock <- openSocket addr when (socketType == Stream) $ connect sock $ addrAddress addr return sock resolve :: SocketType -> Maybe HostName -> ServiceName -> Bool -> IO AddrInfo resolve socketType mhost port passive = head <$> getAddrInfo (Just hints) mhost (Just port) where hints = defaultHints { addrSocketType = socketType , addrFlags = if passive then [AI_PASSIVE] else [] } openSocket :: AddrInfo -> IO Socket openSocket addr = socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr) openServerSocket :: AddrInfo -> IO Socket openServerSocket addr = do sock <- openSocket addr setSocketOption sock ReuseAddr 1 withFdSocket sock $ setCloseOnExecIfNeeded bind sock $ addrAddress addr return sock