module Aws.Network where

import Data.Maybe
import Control.Exception
import Network.BSD (getProtocolNumber)
import Network.Socket
import System.Timeout

-- Make a good guess if a host is reachable.
hostAvailable :: String -> IO Bool
hostAvailable :: ServiceName -> IO Bool
hostAvailable ServiceName
h = do
  Socket
sock <- ServiceName -> IO ProtocolNumber
getProtocolNumber ServiceName
"tcp" forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Family -> SocketType -> ProtocolNumber -> IO Socket
socket Family
AF_INET SocketType
Stream
  SockAddr
addr <- (AddrInfo -> SockAddr
addrAddress forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> a
head) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` Maybe AddrInfo
-> Maybe ServiceName -> Maybe ServiceName -> IO [AddrInfo]
getAddrInfo (forall a. a -> Maybe a
Just (AddrInfo
defaultHints { addrFlags :: [AddrInfoFlag]
addrFlags = [ AddrInfoFlag
AI_PASSIVE ] } )) (forall a. a -> Maybe a
Just ServiceName
h) (forall a. a -> Maybe a
Just ServiceName
"80")
  case SockAddr
addr of
    remote :: SockAddr
remote@(SockAddrInet PortNumber
_ HostAddress
_) -> do
      Bool
v <- forall e a. Exception e => IO a -> (e -> IO a) -> IO a
catch (forall a. Int -> IO a -> IO (Maybe a)
timeout Int
100000 (Socket -> SockAddr -> IO ()
connect Socket
sock SockAddr
remote) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Maybe a -> Bool
isJust)
                 (\(SomeException
_ :: SomeException) -> forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False)
      Socket -> IO ()
close Socket
sock
      forall (m :: * -> *) a. Monad m => a -> m a
return Bool
v
    SockAddr
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False