module Test.Sandwich.Contexts.Kubernetes.Util.SocketUtil (
isPortOpen
, simpleSockAddr
) where
import Foreign.C.Error (Errno(..), eCONNREFUSED)
import GHC.IO.Exception (IOException(..))
import Network.Socket (Family(AF_INET), PortNumber, SocketType(Stream), SockAddr(SockAddrInet), socket, connect, close', tupleToHostAddress)
import Relude
import UnliftIO.Exception
isPortOpen :: SockAddr -> IO Bool
isPortOpen :: SockAddr -> IO Bool
isPortOpen SockAddr
sockAddr = do
IO Socket -> (Socket -> IO ()) -> (Socket -> IO Bool) -> IO Bool
forall (m :: * -> *) a b c.
MonadUnliftIO m =>
m a -> (a -> m b) -> (a -> m c) -> m c
bracket (Family -> SocketType -> ProtocolNumber -> IO Socket
socket Family
AF_INET SocketType
Stream ProtocolNumber
6 ) Socket -> IO ()
close' ((Socket -> IO Bool) -> IO Bool) -> (Socket -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \Socket
sock -> do
res <- IO () -> IO (Either IOException ())
forall (m :: * -> *) e a.
(MonadUnliftIO m, Exception e) =>
m a -> m (Either e a)
try (IO () -> IO (Either IOException ()))
-> IO () -> IO (Either IOException ())
forall a b. (a -> b) -> a -> b
$ Socket -> SockAddr -> IO ()
connect Socket
sock SockAddr
sockAddr
case res of
Right () -> Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
Left IOException
e ->
if (ProtocolNumber -> Errno
Errno (ProtocolNumber -> Errno) -> Maybe ProtocolNumber -> Maybe Errno
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IOException -> Maybe ProtocolNumber
ioe_errno IOException
e) Maybe Errno -> Maybe Errno -> Bool
forall a. Eq a => a -> a -> Bool
== Errno -> Maybe Errno
forall a. a -> Maybe a
Just Errno
eCONNREFUSED
then Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
else IOException -> IO Bool
forall (m :: * -> *) e a. (MonadIO m, Exception e) => e -> m a
throwIO IOException
e
simpleSockAddr :: (Word8, Word8, Word8, Word8) -> PortNumber -> SockAddr
simpleSockAddr :: (Word8, Word8, Word8, Word8) -> PortNumber -> SockAddr
simpleSockAddr (Word8, Word8, Word8, Word8)
addr PortNumber
port = PortNumber -> HostAddress -> SockAddr
SockAddrInet PortNumber
port ((Word8, Word8, Word8, Word8) -> HostAddress
tupleToHostAddress (Word8, Word8, Word8, Word8)
addr)