{-# LANGUAGE CPP #-} module Lambdabot.Util.Network ( connectTo', ) where import Network.Socket import Network.BSD import System.IO import Control.Exception -- |This is essentially a reimplementation of the former Network.connectTo -- function, except that we don't do the service name lookup. -- Code originally from the network package. connectTo' :: HostName -> PortNumber -> IO Handle connectTo' host port = do proto <- getProtocolNumber "tcp" let hints = defaultHints { addrFlags = [AI_ADDRCONFIG] , addrProtocol = proto , addrSocketType = Stream } addrs <- getAddrInfo (Just hints) (Just host) (Just (show port)) firstSuccessful $ map tryToConnect addrs where tryToConnect addr = bracketOnError (socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)) (close) -- only done if there's an error (\sock -> do connect sock (addrAddress addr) socketToHandle sock ReadWriteMode ) firstSuccessful = go [] where go :: [IOException] -> [IO a] -> IO a go [] [] = ioError . userError $ "host name `" ++ show host ++ "` could not be resolved" go l@(_:_) [] = ioError . userError $ "could not connect to host `" ++ show host go acc (act:followingActs) = do er <- try act case er of Left err -> go (err:acc) followingActs Right r -> return r