{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
module Ouroboros.Network.Snocket
(
Accept (..)
, Accepted (..)
, AddressFamily (..)
, Snocket (..)
, SocketSnocket
, socketSnocket
, LocalSnocket
, localSnocket
, LocalSocket (..)
, LocalAddress (..)
, localAddressFromPath
, TestAddress (..)
, FileDescriptor (..)
, socketFileDescriptor
, localSocketFileDescriptor
) where
import Control.Exception
import Control.Monad (when)
import Control.Monad.Class.MonadTime (DiffTime)
import Control.Tracer (Tracer)
import Data.Bifoldable (Bifoldable (..))
import Data.Bifunctor (Bifunctor (..))
import Data.Hashable
import Data.Typeable (Typeable)
import Data.Word
import GHC.Generics (Generic)
import Quiet (Quiet (..))
#if !defined(mingw32_HOST_OS)
import Network.Socket (Family (AF_UNIX))
#endif
import Network.Socket (SockAddr (..), Socket)
#if defined(mingw32_HOST_OS)
import Data.Bits
import Foreign.Ptr (IntPtr (..), ptrToIntPtr)
import qualified System.Win32 as Win32
import qualified System.Win32.Async as Win32.Async
import qualified System.Win32.NamedPipes as Win32
import Network.Mux.Bearer.NamedPipe (namedPipeAsBearer)
#endif
import qualified Network.Socket as Socket
import qualified Network.Mux.Bearer.Socket as Mx
import Network.Mux.Trace (MuxTrace)
import Network.Mux.Types (MuxBearer)
import Ouroboros.Network.IOManager
import Ouroboros.Network.Linger (StructLinger (..))
newtype Accept m fd addr = Accept
{ Accept m fd addr -> m (Accepted fd addr, Accept m fd addr)
runAccept :: m (Accepted fd addr, Accept m fd addr)
}
instance Functor m => Bifunctor (Accept m) where
bimap :: (a -> b) -> (c -> d) -> Accept m a c -> Accept m b d
bimap a -> b
f c -> d
g (Accept m (Accepted a c, Accept m a c)
ac) = m (Accepted b d, Accept m b d) -> Accept m b d
forall (m :: * -> *) fd addr.
m (Accepted fd addr, Accept m fd addr) -> Accept m fd addr
Accept ((Accepted a c, Accept m a c) -> (Accepted b d, Accept m b d)
h ((Accepted a c, Accept m a c) -> (Accepted b d, Accept m b d))
-> m (Accepted a c, Accept m a c) -> m (Accepted b d, Accept m b d)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (Accepted a c, Accept m a c)
ac)
where
h :: (Accepted a c, Accept m a c) -> (Accepted b d, Accept m b d)
h (Accepted a c
accepted, Accept m a c
next) = ((a -> b) -> (c -> d) -> Accepted a c -> Accepted b d
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap a -> b
f c -> d
g Accepted a c
accepted, (a -> b) -> (c -> d) -> Accept m a c -> Accept m b d
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap a -> b
f c -> d
g Accept m a c
next)
data Accepted fd addr where
AcceptFailure :: !SomeException -> Accepted fd addr
Accepted :: !fd -> !addr -> Accepted fd addr
instance Bifunctor Accepted where
bimap :: (a -> b) -> (c -> d) -> Accepted a c -> Accepted b d
bimap a -> b
f c -> d
g (Accepted a
fd c
addr) = b -> d -> Accepted b d
forall fd addr. fd -> addr -> Accepted fd addr
Accepted (a -> b
f a
fd) (c -> d
g c
addr)
bimap a -> b
_ c -> d
_ (AcceptFailure SomeException
err) = SomeException -> Accepted b d
forall fd addr. SomeException -> Accepted fd addr
AcceptFailure SomeException
err
instance Bifoldable Accepted where
bifoldMap :: (a -> m) -> (b -> m) -> Accepted a b -> m
bifoldMap a -> m
f b -> m
g (Accepted a
fd b
addr) = a -> m
f a
fd m -> m -> m
forall a. Semigroup a => a -> a -> a
<> b -> m
g b
addr
bifoldMap a -> m
_ b -> m
_ (AcceptFailure SomeException
_) = m
forall a. Monoid a => a
mempty
berkeleyAccept :: IOManager
-> Socket
-> IO (Accept IO Socket SockAddr)
berkeleyAccept :: IOManager -> Socket -> IO (Accept IO Socket SockAddr)
berkeleyAccept IOManager
ioManager Socket
sock =
Word64 -> SockAddr -> Accept IO Socket SockAddr
go Word64
0 (SockAddr -> Accept IO Socket SockAddr)
-> IO SockAddr -> IO (Accept IO Socket SockAddr)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Socket -> IO SockAddr
Socket.getSocketName Socket
sock
where
go :: Word64 -> SockAddr -> Accept IO Socket SockAddr
go !Word64
cnt !SockAddr
addr = IO (Accepted Socket SockAddr, Accept IO Socket SockAddr)
-> Accept IO Socket SockAddr
forall (m :: * -> *) fd addr.
m (Accepted fd addr, Accept m fd addr) -> Accept m fd addr
Accept (SockAddr
-> Word64
-> IO (Accepted Socket SockAddr, Accept IO Socket SockAddr)
acceptOne SockAddr
addr Word64
cnt IO (Accepted Socket SockAddr, Accept IO Socket SockAddr)
-> (SomeException
-> IO (Accepted Socket SockAddr, Accept IO Socket SockAddr))
-> IO (Accepted Socket SockAddr, Accept IO Socket SockAddr)
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
`catch` SockAddr
-> Word64
-> SomeException
-> IO (Accepted Socket SockAddr, Accept IO Socket SockAddr)
handleException SockAddr
addr Word64
cnt)
acceptOne
:: SockAddr
-> Word64
-> IO ( Accepted Socket SockAddr
, Accept IO Socket SockAddr
)
acceptOne :: SockAddr
-> Word64
-> IO (Accepted Socket SockAddr, Accept IO Socket SockAddr)
acceptOne SockAddr
addr Word64
cnt =
IO (Socket, SockAddr)
-> ((Socket, SockAddr) -> IO ())
-> ((Socket, SockAddr)
-> IO (Accepted Socket SockAddr, Accept IO Socket SockAddr))
-> IO (Accepted Socket SockAddr, Accept IO Socket SockAddr)
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracketOnError
#if !defined(mingw32_HOST_OS)
(Socket -> IO (Socket, SockAddr)
Socket.accept Socket
sock)
#else
(Win32.Async.accept sock)
#endif
(IO () -> IO ()
forall a. IO a -> IO a
uninterruptibleMask_ (IO () -> IO ())
-> ((Socket, SockAddr) -> IO ()) -> (Socket, SockAddr) -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Socket -> IO ()
Socket.close (Socket -> IO ())
-> ((Socket, SockAddr) -> Socket) -> (Socket, SockAddr) -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Socket, SockAddr) -> Socket
forall a b. (a, b) -> a
fst)
(((Socket, SockAddr)
-> IO (Accepted Socket SockAddr, Accept IO Socket SockAddr))
-> IO (Accepted Socket SockAddr, Accept IO Socket SockAddr))
-> ((Socket, SockAddr)
-> IO (Accepted Socket SockAddr, Accept IO Socket SockAddr))
-> IO (Accepted Socket SockAddr, Accept IO Socket SockAddr)
forall a b. (a -> b) -> a -> b
$ \(Socket
sock', SockAddr
addr') -> do
IOManager -> Either Any Socket -> IO ()
IOManager -> forall hole. hole -> IO ()
associateWithIOManager IOManager
ioManager (Socket -> Either Any Socket
forall a b. b -> Either a b
Right Socket
sock')
SockAddr
addr'' <- case SockAddr
addr of
Socket.SockAddrUnix String
path
-> SockAddr -> IO SockAddr
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> SockAddr
Socket.SockAddrUnix (String -> SockAddr) -> String -> SockAddr
forall a b. (a -> b) -> a -> b
$ String
path String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"@" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Word64 -> String
forall a. Show a => a -> String
show Word64
cnt)
SockAddr
_ -> SockAddr -> IO SockAddr
forall (m :: * -> *) a. Monad m => a -> m a
return SockAddr
addr'
(Accepted Socket SockAddr, Accept IO Socket SockAddr)
-> IO (Accepted Socket SockAddr, Accept IO Socket SockAddr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Socket -> SockAddr -> Accepted Socket SockAddr
forall fd addr. fd -> addr -> Accepted fd addr
Accepted Socket
sock' SockAddr
addr'', Word64 -> SockAddr -> Accept IO Socket SockAddr
go (Word64 -> Word64
forall a. Enum a => a -> a
succ Word64
cnt) SockAddr
addr)
handleException
:: SockAddr
-> Word64
-> SomeException
-> IO ( Accepted Socket SockAddr
, Accept IO Socket SockAddr
)
handleException :: SockAddr
-> Word64
-> SomeException
-> IO (Accepted Socket SockAddr, Accept IO Socket SockAddr)
handleException SockAddr
addr Word64
cnt SomeException
err =
case SomeException -> Maybe SomeAsyncException
forall e. Exception e => SomeException -> Maybe e
fromException SomeException
err of
Just (SomeAsyncException e
_) -> SomeException
-> IO (Accepted Socket SockAddr, Accept IO Socket SockAddr)
forall e a. Exception e => e -> IO a
throwIO SomeException
err
Maybe SomeAsyncException
Nothing -> (Accepted Socket SockAddr, Accept IO Socket SockAddr)
-> IO (Accepted Socket SockAddr, Accept IO Socket SockAddr)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SomeException -> Accepted Socket SockAddr
forall fd addr. SomeException -> Accepted fd addr
AcceptFailure SomeException
err, Word64 -> SockAddr -> Accept IO Socket SockAddr
go Word64
cnt SockAddr
addr)
newtype LocalAddress = LocalAddress { LocalAddress -> String
getFilePath :: FilePath }
deriving (LocalAddress -> LocalAddress -> Bool
(LocalAddress -> LocalAddress -> Bool)
-> (LocalAddress -> LocalAddress -> Bool) -> Eq LocalAddress
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: LocalAddress -> LocalAddress -> Bool
$c/= :: LocalAddress -> LocalAddress -> Bool
== :: LocalAddress -> LocalAddress -> Bool
$c== :: LocalAddress -> LocalAddress -> Bool
Eq, Eq LocalAddress
Eq LocalAddress
-> (LocalAddress -> LocalAddress -> Ordering)
-> (LocalAddress -> LocalAddress -> Bool)
-> (LocalAddress -> LocalAddress -> Bool)
-> (LocalAddress -> LocalAddress -> Bool)
-> (LocalAddress -> LocalAddress -> Bool)
-> (LocalAddress -> LocalAddress -> LocalAddress)
-> (LocalAddress -> LocalAddress -> LocalAddress)
-> Ord LocalAddress
LocalAddress -> LocalAddress -> Bool
LocalAddress -> LocalAddress -> Ordering
LocalAddress -> LocalAddress -> LocalAddress
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: LocalAddress -> LocalAddress -> LocalAddress
$cmin :: LocalAddress -> LocalAddress -> LocalAddress
max :: LocalAddress -> LocalAddress -> LocalAddress
$cmax :: LocalAddress -> LocalAddress -> LocalAddress
>= :: LocalAddress -> LocalAddress -> Bool
$c>= :: LocalAddress -> LocalAddress -> Bool
> :: LocalAddress -> LocalAddress -> Bool
$c> :: LocalAddress -> LocalAddress -> Bool
<= :: LocalAddress -> LocalAddress -> Bool
$c<= :: LocalAddress -> LocalAddress -> Bool
< :: LocalAddress -> LocalAddress -> Bool
$c< :: LocalAddress -> LocalAddress -> Bool
compare :: LocalAddress -> LocalAddress -> Ordering
$ccompare :: LocalAddress -> LocalAddress -> Ordering
$cp1Ord :: Eq LocalAddress
Ord, (forall x. LocalAddress -> Rep LocalAddress x)
-> (forall x. Rep LocalAddress x -> LocalAddress)
-> Generic LocalAddress
forall x. Rep LocalAddress x -> LocalAddress
forall x. LocalAddress -> Rep LocalAddress x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep LocalAddress x -> LocalAddress
$cfrom :: forall x. LocalAddress -> Rep LocalAddress x
Generic)
deriving Int -> LocalAddress -> String -> String
[LocalAddress] -> String -> String
LocalAddress -> String
(Int -> LocalAddress -> String -> String)
-> (LocalAddress -> String)
-> ([LocalAddress] -> String -> String)
-> Show LocalAddress
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [LocalAddress] -> String -> String
$cshowList :: [LocalAddress] -> String -> String
show :: LocalAddress -> String
$cshow :: LocalAddress -> String
showsPrec :: Int -> LocalAddress -> String -> String
$cshowsPrec :: Int -> LocalAddress -> String -> String
Show via Quiet LocalAddress
instance Hashable LocalAddress where
hashWithSalt :: Int -> LocalAddress -> Int
hashWithSalt Int
s (LocalAddress String
path) = Int -> String -> Int
forall a. Hashable a => Int -> a -> Int
hashWithSalt Int
s String
path
newtype TestAddress addr = TestAddress { TestAddress addr -> addr
getTestAddress :: addr }
deriving (TestAddress addr -> TestAddress addr -> Bool
(TestAddress addr -> TestAddress addr -> Bool)
-> (TestAddress addr -> TestAddress addr -> Bool)
-> Eq (TestAddress addr)
forall addr.
Eq addr =>
TestAddress addr -> TestAddress addr -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TestAddress addr -> TestAddress addr -> Bool
$c/= :: forall addr.
Eq addr =>
TestAddress addr -> TestAddress addr -> Bool
== :: TestAddress addr -> TestAddress addr -> Bool
$c== :: forall addr.
Eq addr =>
TestAddress addr -> TestAddress addr -> Bool
Eq, Eq (TestAddress addr)
Eq (TestAddress addr)
-> (TestAddress addr -> TestAddress addr -> Ordering)
-> (TestAddress addr -> TestAddress addr -> Bool)
-> (TestAddress addr -> TestAddress addr -> Bool)
-> (TestAddress addr -> TestAddress addr -> Bool)
-> (TestAddress addr -> TestAddress addr -> Bool)
-> (TestAddress addr -> TestAddress addr -> TestAddress addr)
-> (TestAddress addr -> TestAddress addr -> TestAddress addr)
-> Ord (TestAddress addr)
TestAddress addr -> TestAddress addr -> Bool
TestAddress addr -> TestAddress addr -> Ordering
TestAddress addr -> TestAddress addr -> TestAddress addr
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall addr. Ord addr => Eq (TestAddress addr)
forall addr.
Ord addr =>
TestAddress addr -> TestAddress addr -> Bool
forall addr.
Ord addr =>
TestAddress addr -> TestAddress addr -> Ordering
forall addr.
Ord addr =>
TestAddress addr -> TestAddress addr -> TestAddress addr
min :: TestAddress addr -> TestAddress addr -> TestAddress addr
$cmin :: forall addr.
Ord addr =>
TestAddress addr -> TestAddress addr -> TestAddress addr
max :: TestAddress addr -> TestAddress addr -> TestAddress addr
$cmax :: forall addr.
Ord addr =>
TestAddress addr -> TestAddress addr -> TestAddress addr
>= :: TestAddress addr -> TestAddress addr -> Bool
$c>= :: forall addr.
Ord addr =>
TestAddress addr -> TestAddress addr -> Bool
> :: TestAddress addr -> TestAddress addr -> Bool
$c> :: forall addr.
Ord addr =>
TestAddress addr -> TestAddress addr -> Bool
<= :: TestAddress addr -> TestAddress addr -> Bool
$c<= :: forall addr.
Ord addr =>
TestAddress addr -> TestAddress addr -> Bool
< :: TestAddress addr -> TestAddress addr -> Bool
$c< :: forall addr.
Ord addr =>
TestAddress addr -> TestAddress addr -> Bool
compare :: TestAddress addr -> TestAddress addr -> Ordering
$ccompare :: forall addr.
Ord addr =>
TestAddress addr -> TestAddress addr -> Ordering
$cp1Ord :: forall addr. Ord addr => Eq (TestAddress addr)
Ord, (forall x. TestAddress addr -> Rep (TestAddress addr) x)
-> (forall x. Rep (TestAddress addr) x -> TestAddress addr)
-> Generic (TestAddress addr)
forall x. Rep (TestAddress addr) x -> TestAddress addr
forall x. TestAddress addr -> Rep (TestAddress addr) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall addr x. Rep (TestAddress addr) x -> TestAddress addr
forall addr x. TestAddress addr -> Rep (TestAddress addr) x
$cto :: forall addr x. Rep (TestAddress addr) x -> TestAddress addr
$cfrom :: forall addr x. TestAddress addr -> Rep (TestAddress addr) x
Generic, Typeable)
deriving Int -> TestAddress addr -> String -> String
[TestAddress addr] -> String -> String
TestAddress addr -> String
(Int -> TestAddress addr -> String -> String)
-> (TestAddress addr -> String)
-> ([TestAddress addr] -> String -> String)
-> Show (TestAddress addr)
forall addr.
Show addr =>
Int -> TestAddress addr -> String -> String
forall addr. Show addr => [TestAddress addr] -> String -> String
forall addr. Show addr => TestAddress addr -> String
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [TestAddress addr] -> String -> String
$cshowList :: forall addr. Show addr => [TestAddress addr] -> String -> String
show :: TestAddress addr -> String
$cshow :: forall addr. Show addr => TestAddress addr -> String
showsPrec :: Int -> TestAddress addr -> String -> String
$cshowsPrec :: forall addr.
Show addr =>
Int -> TestAddress addr -> String -> String
Show via Quiet (TestAddress addr)
data AddressFamily addr where
SocketFamily :: !Socket.Family
-> AddressFamily Socket.SockAddr
LocalFamily :: !LocalAddress -> AddressFamily LocalAddress
TestFamily :: AddressFamily (TestAddress addr)
deriving instance Eq addr => Eq (AddressFamily addr)
deriving instance Show addr => Show (AddressFamily addr)
data Snocket m fd addr = Snocket {
Snocket m fd addr -> fd -> m addr
getLocalAddr :: fd -> m addr
, Snocket m fd addr -> fd -> m addr
getRemoteAddr :: fd -> m addr
, Snocket m fd addr -> addr -> AddressFamily addr
addrFamily :: addr -> AddressFamily addr
, Snocket m fd addr -> AddressFamily addr -> m fd
open :: AddressFamily addr -> m fd
, Snocket m fd addr -> addr -> m fd
openToConnect :: addr -> m fd
, Snocket m fd addr -> fd -> addr -> m ()
connect :: fd -> addr -> m ()
, Snocket m fd addr -> fd -> addr -> m ()
bind :: fd -> addr -> m ()
, Snocket m fd addr -> fd -> m ()
listen :: fd -> m ()
, Snocket m fd addr -> fd -> m (Accept m fd addr)
accept :: fd -> m (Accept m fd addr)
, Snocket m fd addr -> fd -> m ()
close :: fd -> m ()
, Snocket m fd addr
-> DiffTime -> Tracer m MuxTrace -> fd -> m (MuxBearer m)
toBearer :: DiffTime -> Tracer m MuxTrace -> fd -> m (MuxBearer m)
}
pureBearer :: Monad m
=> (DiffTime -> Tracer m MuxTrace -> fd -> MuxBearer m)
-> DiffTime -> Tracer m MuxTrace -> fd -> m (MuxBearer m)
pureBearer :: (DiffTime -> Tracer m MuxTrace -> fd -> MuxBearer m)
-> DiffTime -> Tracer m MuxTrace -> fd -> m (MuxBearer m)
pureBearer DiffTime -> Tracer m MuxTrace -> fd -> MuxBearer m
f = \DiffTime
timeout Tracer m MuxTrace
tr fd
fd -> MuxBearer m -> m (MuxBearer m)
forall (m :: * -> *) a. Monad m => a -> m a
return (DiffTime -> Tracer m MuxTrace -> fd -> MuxBearer m
f DiffTime
timeout Tracer m MuxTrace
tr fd
fd)
socketAddrFamily
:: Socket.SockAddr
-> AddressFamily Socket.SockAddr
socketAddrFamily :: SockAddr -> AddressFamily SockAddr
socketAddrFamily (Socket.SockAddrInet PortNumber
_ HostAddress
_ ) = Family -> AddressFamily SockAddr
SocketFamily Family
Socket.AF_INET
socketAddrFamily (Socket.SockAddrInet6 PortNumber
_ HostAddress
_ HostAddress6
_ HostAddress
_) = Family -> AddressFamily SockAddr
SocketFamily Family
Socket.AF_INET6
socketAddrFamily (Socket.SockAddrUnix String
_ ) = Family -> AddressFamily SockAddr
SocketFamily Family
Socket.AF_UNIX
type SocketSnocket = Snocket IO Socket SockAddr
socketSnocket
:: IOManager
-> SocketSnocket
socketSnocket :: IOManager -> SocketSnocket
socketSnocket IOManager
ioManager = Snocket :: forall (m :: * -> *) fd addr.
(fd -> m addr)
-> (fd -> m addr)
-> (addr -> AddressFamily addr)
-> (AddressFamily addr -> m fd)
-> (addr -> m fd)
-> (fd -> addr -> m ())
-> (fd -> addr -> m ())
-> (fd -> m ())
-> (fd -> m (Accept m fd addr))
-> (fd -> m ())
-> (DiffTime -> Tracer m MuxTrace -> fd -> m (MuxBearer m))
-> Snocket m fd addr
Snocket {
getLocalAddr :: Socket -> IO SockAddr
getLocalAddr = Socket -> IO SockAddr
Socket.getSocketName
, getRemoteAddr :: Socket -> IO SockAddr
getRemoteAddr = Socket -> IO SockAddr
Socket.getPeerName
, addrFamily :: SockAddr -> AddressFamily SockAddr
addrFamily = SockAddr -> AddressFamily SockAddr
socketAddrFamily
, open :: AddressFamily SockAddr -> IO Socket
open = AddressFamily SockAddr -> IO Socket
openSocket
, openToConnect :: SockAddr -> IO Socket
openToConnect = \SockAddr
addr -> AddressFamily SockAddr -> IO Socket
openSocket (SockAddr -> AddressFamily SockAddr
socketAddrFamily SockAddr
addr)
, connect :: Socket -> SockAddr -> IO ()
connect = \Socket
s SockAddr
a -> do
#if !defined(mingw32_HOST_OS)
Socket -> SockAddr -> IO ()
Socket.connect Socket
s SockAddr
a
#else
Win32.Async.connect s a
#endif
, bind :: Socket -> SockAddr -> IO ()
bind = \Socket
sd SockAddr
addr -> do
let SocketFamily Family
fml = SockAddr -> AddressFamily SockAddr
socketAddrFamily SockAddr
addr
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Family
fml Family -> Family -> Bool
forall a. Eq a => a -> a -> Bool
== Family
Socket.AF_INET Bool -> Bool -> Bool
||
Family
fml Family -> Family -> Bool
forall a. Eq a => a -> a -> Bool
== Family
Socket.AF_INET6) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
Socket -> SocketOption -> Int -> IO ()
Socket.setSocketOption Socket
sd SocketOption
Socket.ReuseAddr Int
1
#if !defined(mingw32_HOST_OS)
Socket -> SocketOption -> Int -> IO ()
Socket.setSocketOption Socket
sd SocketOption
Socket.ReusePort Int
1
#endif
Socket -> SocketOption -> Int -> IO ()
Socket.setSocketOption Socket
sd SocketOption
Socket.NoDelay Int
1
Socket -> SocketOption -> StructLinger -> IO ()
forall a. Storable a => Socket -> SocketOption -> a -> IO ()
Socket.setSockOpt Socket
sd SocketOption
Socket.Linger
(StructLinger :: CInt -> CInt -> StructLinger
StructLinger { sl_onoff :: CInt
sl_onoff = CInt
1,
sl_linger :: CInt
sl_linger = CInt
0 })
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Family
fml Family -> Family -> Bool
forall a. Eq a => a -> a -> Bool
== Family
Socket.AF_INET6)
(IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Socket -> SocketOption -> Int -> IO ()
Socket.setSocketOption Socket
sd SocketOption
Socket.IPv6Only Int
1
Socket -> SockAddr -> IO ()
Socket.bind Socket
sd SockAddr
addr
, listen :: Socket -> IO ()
listen = \Socket
s -> Socket -> Int -> IO ()
Socket.listen Socket
s Int
8
, accept :: Socket -> IO (Accept IO Socket SockAddr)
accept = IOManager -> Socket -> IO (Accept IO Socket SockAddr)
berkeleyAccept IOManager
ioManager
, close :: Socket -> IO ()
close = IO () -> IO ()
forall a. IO a -> IO a
uninterruptibleMask_ (IO () -> IO ()) -> (Socket -> IO ()) -> Socket -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Socket -> IO ()
Socket.close
, toBearer :: DiffTime -> Tracer IO MuxTrace -> Socket -> IO (MuxBearer IO)
toBearer = (DiffTime -> Tracer IO MuxTrace -> Socket -> MuxBearer IO)
-> DiffTime -> Tracer IO MuxTrace -> Socket -> IO (MuxBearer IO)
forall (m :: * -> *) fd.
Monad m =>
(DiffTime -> Tracer m MuxTrace -> fd -> MuxBearer m)
-> DiffTime -> Tracer m MuxTrace -> fd -> m (MuxBearer m)
pureBearer DiffTime -> Tracer IO MuxTrace -> Socket -> MuxBearer IO
Mx.socketAsMuxBearer
}
where
openSocket :: AddressFamily SockAddr -> IO Socket
openSocket :: AddressFamily SockAddr -> IO Socket
openSocket (SocketFamily Family
family_) = do
Socket
sd <- Family -> SocketType -> CInt -> IO Socket
Socket.socket Family
family_ SocketType
Socket.Stream CInt
Socket.defaultProtocol
IOManager -> Either Any Socket -> IO ()
IOManager -> forall hole. hole -> IO ()
associateWithIOManager IOManager
ioManager (Socket -> Either Any Socket
forall a b. b -> Either a b
Right Socket
sd)
IO () -> (IOException -> IO ()) -> IO ()
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
`catch` \(IOException
e :: IOException) -> do
Socket -> IO ()
Socket.close Socket
sd
IOException -> IO ()
forall e a. Exception e => e -> IO a
throwIO IOException
e
IO () -> (SomeAsyncException -> IO ()) -> IO ()
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
`catch` \(SomeAsyncException e
_) -> do
Socket -> IO ()
Socket.close Socket
sd
IOException -> IO ()
forall e a. Exception e => e -> IO a
throwIO IOException
e
Socket -> IO Socket
forall (m :: * -> *) a. Monad m => a -> m a
return Socket
sd
#if defined(mingw32_HOST_OS)
type LocalHandle = Win32.HANDLE
#else
type LocalHandle = Socket
#endif
#if defined(mingw32_HOST_OS)
data LocalSocket = LocalSocket { getLocalHandle :: !LocalHandle
, getLocalPath :: !LocalAddress
, getRemotePath :: !LocalAddress
}
deriving (Eq, Generic)
deriving Show via Quiet LocalSocket
#else
newtype LocalSocket = LocalSocket { LocalSocket -> Socket
getLocalHandle :: LocalHandle }
deriving (LocalSocket -> LocalSocket -> Bool
(LocalSocket -> LocalSocket -> Bool)
-> (LocalSocket -> LocalSocket -> Bool) -> Eq LocalSocket
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: LocalSocket -> LocalSocket -> Bool
$c/= :: LocalSocket -> LocalSocket -> Bool
== :: LocalSocket -> LocalSocket -> Bool
$c== :: LocalSocket -> LocalSocket -> Bool
Eq, (forall x. LocalSocket -> Rep LocalSocket x)
-> (forall x. Rep LocalSocket x -> LocalSocket)
-> Generic LocalSocket
forall x. Rep LocalSocket x -> LocalSocket
forall x. LocalSocket -> Rep LocalSocket x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep LocalSocket x -> LocalSocket
$cfrom :: forall x. LocalSocket -> Rep LocalSocket x
Generic)
deriving Int -> LocalSocket -> String -> String
[LocalSocket] -> String -> String
LocalSocket -> String
(Int -> LocalSocket -> String -> String)
-> (LocalSocket -> String)
-> ([LocalSocket] -> String -> String)
-> Show LocalSocket
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [LocalSocket] -> String -> String
$cshowList :: [LocalSocket] -> String -> String
show :: LocalSocket -> String
$cshow :: LocalSocket -> String
showsPrec :: Int -> LocalSocket -> String -> String
$cshowsPrec :: Int -> LocalSocket -> String -> String
Show via Quiet LocalSocket
#endif
type LocalSnocket = Snocket IO LocalSocket LocalAddress
localSnocket :: IOManager -> LocalSnocket
#if defined(mingw32_HOST_OS)
localSnocket ioManager = Snocket {
getLocalAddr = return . getLocalPath
, getRemoteAddr = return . getRemotePath
, addrFamily = LocalFamily
, open = \(LocalFamily addr) -> do
hpipe <- Win32.createNamedPipe
(getFilePath addr)
(Win32.pIPE_ACCESS_DUPLEX .|. Win32.fILE_FLAG_OVERLAPPED)
(Win32.pIPE_TYPE_BYTE .|. Win32.pIPE_READMODE_BYTE)
Win32.pIPE_UNLIMITED_INSTANCES
65536
16384
0
Nothing
associateWithIOManager ioManager (Left hpipe)
`catch` \(e :: IOException) -> do
Win32.closeHandle hpipe
throwIO e
`catch` \(SomeAsyncException _) -> do
Win32.closeHandle hpipe
throwIO e
pure (LocalSocket hpipe addr (LocalAddress ""))
, openToConnect = \(LocalAddress pipeName) -> do
hpipe <- Win32.connect pipeName
(Win32.gENERIC_READ .|. Win32.gENERIC_WRITE )
Win32.fILE_SHARE_NONE
Nothing
Win32.oPEN_EXISTING
Win32.fILE_FLAG_OVERLAPPED
Nothing
associateWithIOManager ioManager (Left hpipe)
`catch` \(e :: IOException) -> do
Win32.closeHandle hpipe
throwIO e
`catch` \(SomeAsyncException _) -> do
Win32.closeHandle hpipe
throwIO e
return (LocalSocket hpipe (LocalAddress pipeName) (LocalAddress pipeName))
, connect = \_ _ -> pure ()
, bind = \_ _ -> pure ()
, listen = \_ -> pure ()
, accept = \sock@(LocalSocket hpipe addr _) -> pure $ Accept $ do
Win32.Async.connectNamedPipe hpipe
return (Accepted sock addr, acceptNext 0 addr)
, close = Win32.closeHandle . getLocalHandle
, toBearer = \_sduTimeout tr -> pure . namedPipeAsBearer tr . getLocalHandle
}
where
acceptNext :: Word64 -> LocalAddress -> Accept IO LocalSocket LocalAddress
acceptNext !cnt addr = Accept (acceptOne `catch` handleIOException)
where
handleIOException
:: IOException
-> IO ( Accepted LocalSocket LocalAddress
, Accept IO LocalSocket LocalAddress
)
handleIOException err =
pure ( AcceptFailure (toException err)
, acceptNext (succ cnt) addr
)
acceptOne
:: IO ( Accepted LocalSocket LocalAddress
, Accept IO LocalSocket LocalAddress
)
acceptOne =
bracketOnError
(Win32.createNamedPipe
(getFilePath addr)
(Win32.pIPE_ACCESS_DUPLEX .|. Win32.fILE_FLAG_OVERLAPPED)
(Win32.pIPE_TYPE_BYTE .|. Win32.pIPE_READMODE_BYTE)
Win32.pIPE_UNLIMITED_INSTANCES
65536
16384
0
Nothing)
Win32.closeHandle
$ \hpipe -> do
associateWithIOManager ioManager (Left hpipe)
Win32.Async.connectNamedPipe hpipe
let addr' = LocalAddress $ getFilePath addr ++ "@" ++ show cnt
return (Accepted (LocalSocket hpipe addr addr') addr', acceptNext (succ cnt) addr)
#else
localSnocket :: IOManager -> LocalSnocket
localSnocket IOManager
ioManager =
Snocket :: forall (m :: * -> *) fd addr.
(fd -> m addr)
-> (fd -> m addr)
-> (addr -> AddressFamily addr)
-> (AddressFamily addr -> m fd)
-> (addr -> m fd)
-> (fd -> addr -> m ())
-> (fd -> addr -> m ())
-> (fd -> m ())
-> (fd -> m (Accept m fd addr))
-> (fd -> m ())
-> (DiffTime -> Tracer m MuxTrace -> fd -> m (MuxBearer m))
-> Snocket m fd addr
Snocket {
getLocalAddr :: LocalSocket -> IO LocalAddress
getLocalAddr = (SockAddr -> LocalAddress) -> IO SockAddr -> IO LocalAddress
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap SockAddr -> LocalAddress
toLocalAddress (IO SockAddr -> IO LocalAddress)
-> (LocalSocket -> IO SockAddr) -> LocalSocket -> IO LocalAddress
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Socket -> IO SockAddr
Socket.getSocketName (Socket -> IO SockAddr)
-> (LocalSocket -> Socket) -> LocalSocket -> IO SockAddr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LocalSocket -> Socket
getLocalHandle
, getRemoteAddr :: LocalSocket -> IO LocalAddress
getRemoteAddr = (SockAddr -> LocalAddress) -> IO SockAddr -> IO LocalAddress
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap SockAddr -> LocalAddress
toLocalAddress (IO SockAddr -> IO LocalAddress)
-> (LocalSocket -> IO SockAddr) -> LocalSocket -> IO LocalAddress
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Socket -> IO SockAddr
Socket.getPeerName (Socket -> IO SockAddr)
-> (LocalSocket -> Socket) -> LocalSocket -> IO SockAddr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LocalSocket -> Socket
getLocalHandle
, addrFamily :: LocalAddress -> AddressFamily LocalAddress
addrFamily = LocalAddress -> AddressFamily LocalAddress
LocalFamily
, connect :: LocalSocket -> LocalAddress -> IO ()
connect = \(LocalSocket Socket
s) LocalAddress
addr ->
Socket -> SockAddr -> IO ()
Socket.connect Socket
s (LocalAddress -> SockAddr
fromLocalAddress LocalAddress
addr)
, bind :: LocalSocket -> LocalAddress -> IO ()
bind = \(LocalSocket Socket
fd) LocalAddress
addr -> Socket -> SockAddr -> IO ()
Socket.bind Socket
fd (LocalAddress -> SockAddr
fromLocalAddress LocalAddress
addr)
, listen :: LocalSocket -> IO ()
listen = (Socket -> Int -> IO ()) -> Int -> Socket -> IO ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip Socket -> Int -> IO ()
Socket.listen Int
8 (Socket -> IO ())
-> (LocalSocket -> Socket) -> LocalSocket -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LocalSocket -> Socket
getLocalHandle
, accept :: LocalSocket -> IO (Accept IO LocalSocket LocalAddress)
accept = (Accept IO Socket SockAddr -> Accept IO LocalSocket LocalAddress)
-> IO (Accept IO Socket SockAddr)
-> IO (Accept IO LocalSocket LocalAddress)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Socket -> LocalSocket)
-> (SockAddr -> LocalAddress)
-> Accept IO Socket SockAddr
-> Accept IO LocalSocket LocalAddress
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap Socket -> LocalSocket
LocalSocket SockAddr -> LocalAddress
toLocalAddress)
(IO (Accept IO Socket SockAddr)
-> IO (Accept IO LocalSocket LocalAddress))
-> (LocalSocket -> IO (Accept IO Socket SockAddr))
-> LocalSocket
-> IO (Accept IO LocalSocket LocalAddress)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IOManager -> Socket -> IO (Accept IO Socket SockAddr)
berkeleyAccept IOManager
ioManager
(Socket -> IO (Accept IO Socket SockAddr))
-> (LocalSocket -> Socket)
-> LocalSocket
-> IO (Accept IO Socket SockAddr)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LocalSocket -> Socket
getLocalHandle
, open :: AddressFamily LocalAddress -> IO LocalSocket
open = AddressFamily LocalAddress -> IO LocalSocket
openSocket
, openToConnect :: LocalAddress -> IO LocalSocket
openToConnect = \LocalAddress
addr -> AddressFamily LocalAddress -> IO LocalSocket
openSocket (LocalAddress -> AddressFamily LocalAddress
LocalFamily LocalAddress
addr)
, close :: LocalSocket -> IO ()
close = IO () -> IO ()
forall a. IO a -> IO a
uninterruptibleMask_ (IO () -> IO ()) -> (LocalSocket -> IO ()) -> LocalSocket -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Socket -> IO ()
Socket.close (Socket -> IO ())
-> (LocalSocket -> Socket) -> LocalSocket -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LocalSocket -> Socket
getLocalHandle
, toBearer :: DiffTime -> Tracer IO MuxTrace -> LocalSocket -> IO (MuxBearer IO)
toBearer = \DiffTime
df Tracer IO MuxTrace
tr (LocalSocket Socket
sd) -> MuxBearer IO -> IO (MuxBearer IO)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (DiffTime -> Tracer IO MuxTrace -> Socket -> MuxBearer IO
Mx.socketAsMuxBearer DiffTime
df Tracer IO MuxTrace
tr Socket
sd)
}
where
toLocalAddress :: SockAddr -> LocalAddress
toLocalAddress :: SockAddr -> LocalAddress
toLocalAddress (SockAddrUnix String
path) = String -> LocalAddress
LocalAddress String
path
toLocalAddress SockAddr
_ = String -> LocalAddress
forall a. HasCallStack => String -> a
error String
"localSnocket.toLocalAddr: impossible happened"
fromLocalAddress :: LocalAddress -> SockAddr
fromLocalAddress :: LocalAddress -> SockAddr
fromLocalAddress = String -> SockAddr
SockAddrUnix (String -> SockAddr)
-> (LocalAddress -> String) -> LocalAddress -> SockAddr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LocalAddress -> String
getFilePath
openSocket :: AddressFamily LocalAddress -> IO LocalSocket
openSocket :: AddressFamily LocalAddress -> IO LocalSocket
openSocket (LocalFamily LocalAddress
_addr) = do
Socket
sd <- Family -> SocketType -> CInt -> IO Socket
Socket.socket Family
AF_UNIX SocketType
Socket.Stream CInt
Socket.defaultProtocol
IOManager -> Either Any Socket -> IO ()
IOManager -> forall hole. hole -> IO ()
associateWithIOManager IOManager
ioManager (Socket -> Either Any Socket
forall a b. b -> Either a b
Right Socket
sd)
IO () -> (IOException -> IO ()) -> IO ()
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
`catch` \(IOException
e :: IOException) -> do
Socket -> IO ()
Socket.close Socket
sd
IOException -> IO ()
forall e a. Exception e => e -> IO a
throwIO IOException
e
IO () -> (SomeAsyncException -> IO ()) -> IO ()
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
`catch` \(SomeAsyncException e
_) -> do
Socket -> IO ()
Socket.close Socket
sd
IOException -> IO ()
forall e a. Exception e => e -> IO a
throwIO IOException
e
LocalSocket -> IO LocalSocket
forall (m :: * -> *) a. Monad m => a -> m a
return (Socket -> LocalSocket
LocalSocket Socket
sd)
#endif
localAddressFromPath :: FilePath -> LocalAddress
localAddressFromPath :: String -> LocalAddress
localAddressFromPath = String -> LocalAddress
LocalAddress
newtype FileDescriptor = FileDescriptor { FileDescriptor -> Int
getFileDescriptor :: Int }
deriving (forall x. FileDescriptor -> Rep FileDescriptor x)
-> (forall x. Rep FileDescriptor x -> FileDescriptor)
-> Generic FileDescriptor
forall x. Rep FileDescriptor x -> FileDescriptor
forall x. FileDescriptor -> Rep FileDescriptor x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep FileDescriptor x -> FileDescriptor
$cfrom :: forall x. FileDescriptor -> Rep FileDescriptor x
Generic
deriving Int -> FileDescriptor -> String -> String
[FileDescriptor] -> String -> String
FileDescriptor -> String
(Int -> FileDescriptor -> String -> String)
-> (FileDescriptor -> String)
-> ([FileDescriptor] -> String -> String)
-> Show FileDescriptor
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [FileDescriptor] -> String -> String
$cshowList :: [FileDescriptor] -> String -> String
show :: FileDescriptor -> String
$cshow :: FileDescriptor -> String
showsPrec :: Int -> FileDescriptor -> String -> String
$cshowsPrec :: Int -> FileDescriptor -> String -> String
Show via Quiet FileDescriptor
socketFileDescriptor :: Socket -> IO FileDescriptor
socketFileDescriptor :: Socket -> IO FileDescriptor
socketFileDescriptor = (CInt -> FileDescriptor) -> IO CInt -> IO FileDescriptor
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int -> FileDescriptor
FileDescriptor (Int -> FileDescriptor) -> (CInt -> Int) -> CInt -> FileDescriptor
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral) (IO CInt -> IO FileDescriptor)
-> (Socket -> IO CInt) -> Socket -> IO FileDescriptor
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Socket -> IO CInt
Socket.unsafeFdSocket
localSocketFileDescriptor :: LocalSocket -> IO FileDescriptor
#if defined(mingw32_HOST_OS)
localSocketFileDescriptor =
\(LocalSocket fd _ _) -> case ptrToIntPtr fd of
IntPtr i -> return (FileDescriptor i)
#else
localSocketFileDescriptor :: LocalSocket -> IO FileDescriptor
localSocketFileDescriptor = Socket -> IO FileDescriptor
socketFileDescriptor (Socket -> IO FileDescriptor)
-> (LocalSocket -> Socket) -> LocalSocket -> IO FileDescriptor
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LocalSocket -> Socket
getLocalHandle
#endif