module Dahdit.Network
  ( Decoder (..)
  , runDecoder
  , Encoder (..)
  , runEncoder
  , Conn (..)
  , HostPort (..)
  , TcpOpts (..)
  , resolveAddr
  , tcpClientConn
  , withTcpClientConn
  , tcpServerConn
  , udpClientConn
  , withUdpClientConn
  , udpServerConn
  , withUdpServerConn
  )
where

import Control.Monad (unless, (>=>))
import Control.Monad.IO.Class (liftIO)
import Control.Monad.IO.Unlift (MonadUnliftIO)
import Dahdit (Binary (..), ByteCount (..), Get, GetError, GetIncCb, GetIncRequest (..), Put, getEnd, getTarget, getTargetInc, putTarget)
import Data.Acquire (Acquire, mkAcquire, withAcquire)
import Data.ByteString (ByteString)
import Data.ByteString qualified as BS
import Data.IORef (IORef, modifyIORef', newIORef, readIORef)
import Data.Tuple (swap)
import Network.Socket qualified as NS
import Network.Socket.ByteString qualified as NSB

maxRecv :: Int
maxRecv :: Int
maxRecv = Int
65535

maxQueue :: Int
maxQueue :: Int
maxQueue = Int
1024

sockRecvUntil :: NS.Socket -> IORef ByteString -> Int -> IO ()
sockRecvUntil :: Socket -> IORef ByteString -> Int -> IO ()
sockRecvUntil Socket
sock IORef ByteString
ref Int
len = IO ()
go
 where
  go :: IO ()
go = do
    ByteString
lastBs <- forall a. IORef a -> IO a
readIORef IORef ByteString
ref
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (ByteString -> Int
BS.length ByteString
lastBs forall a. Ord a => a -> a -> Bool
>= Int
len) forall a b. (a -> b) -> a -> b
$ do
      ByteString
chunkBs <- Socket -> Int -> IO ByteString
NSB.recv Socket
sock Int
maxRecv
      forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' IORef ByteString
ref (forall a. Semigroup a => a -> a -> a
<> ByteString
chunkBs)
      forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (ByteString -> Bool
BS.null ByteString
chunkBs) IO ()
go

-- Appropriate for TCP connections (uses 'recv' instead of 'recvFrom')
sockGetIncCb :: NS.Socket -> IO (GetIncCb ByteString IO)
sockGetIncCb :: Socket -> IO (GetIncCb ByteString IO)
sockGetIncCb Socket
sock = do
  IORef ByteString
ref <- forall a. a -> IO (IORef a)
newIORef forall a. Monoid a => a
mempty
  forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ \(GetIncRequest ByteCount
_ (ByteCount Int
off) (ByteCount Int
len)) -> do
    forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' IORef ByteString
ref (Int -> ByteString -> ByteString
BS.drop Int
off)
    Socket -> IORef ByteString -> Int -> IO ()
sockRecvUntil Socket
sock IORef ByteString
ref Int
len
    ByteString
nextBs <- forall a. IORef a -> IO a
readIORef IORef ByteString
ref
    forall (f :: * -> *) a. Applicative f => a -> f a
pure (if ByteString -> Int
BS.length ByteString
nextBs forall a. Ord a => a -> a -> Bool
>= Int
len then forall a. Maybe a
Nothing else forall a. a -> Maybe a
Just ByteString
nextBs)

newtype Decoder k = Decoder {forall k. Decoder k -> forall a. Get a -> IO (k, Either GetError a)
unDecoder :: forall a. Get a -> IO (k, Either GetError a)}
  deriving stock (forall a b. a -> Decoder b -> Decoder a
forall a b. (a -> b) -> Decoder a -> Decoder b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> Decoder b -> Decoder a
$c<$ :: forall a b. a -> Decoder b -> Decoder a
fmap :: forall a b. (a -> b) -> Decoder a -> Decoder b
$cfmap :: forall a b. (a -> b) -> Decoder a -> Decoder b
Functor)

runDecoder :: (Binary a) => Decoder k -> IO (k, Either GetError a)
runDecoder :: forall a k. Binary a => Decoder k -> IO (k, Either GetError a)
runDecoder Decoder k
dec = forall k. Decoder k -> forall a. Get a -> IO (k, Either GetError a)
unDecoder Decoder k
dec forall a. Binary a => Get a
get

-- | Decodes a stream of packets incrementally for TCP
streamDecoder :: Maybe ByteCount -> NS.Socket -> IO (Decoder ())
streamDecoder :: Maybe ByteCount -> Socket -> IO (Decoder ())
streamDecoder Maybe ByteCount
mayLim Socket
sock = do
  GetIncCb ByteString IO
cb <- Socket -> IO (GetIncCb ByteString IO)
sockGetIncCb Socket
sock
  forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall k.
(forall a. Get a -> IO (k, Either GetError a)) -> Decoder k
Decoder (\Get a
getter -> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(Either GetError a
res, ByteCount
_, ByteCount
_) -> ((), Either GetError a
res)) (forall z (m :: * -> *) a.
BinaryGetTarget z m =>
Maybe ByteCount
-> Get a
-> GetIncCb z m
-> m (Either GetError a, ByteCount, ByteCount)
getTargetInc Maybe ByteCount
mayLim Get a
getter GetIncCb ByteString IO
cb)))

-- | Completely decodes one packet at a time for UDP server
datagramServerDecoder :: Maybe ByteCount -> NS.Socket -> Decoder NS.SockAddr
datagramServerDecoder :: Maybe ByteCount -> Socket -> Decoder SockAddr
datagramServerDecoder Maybe ByteCount
mayLim Socket
sock =
  let lim :: Int
lim = forall b a. b -> (a -> b) -> Maybe a -> b
maybe Int
maxRecv ByteCount -> Int
unByteCount Maybe ByteCount
mayLim
  in  forall k.
(forall a. Get a -> IO (k, Either GetError a)) -> Decoder k
Decoder forall a b. (a -> b) -> a -> b
$ \Get a
getter -> do
        (ByteString
bs, SockAddr
addr) <- Socket -> Int -> IO (ByteString, SockAddr)
NSB.recvFrom Socket
sock Int
lim
        (Either GetError a
ea, ByteCount
_) <- forall z (m :: * -> *) a.
BinaryGetTarget z m =>
Get a -> z -> m (Either GetError a, ByteCount)
getTarget (forall a. Get a -> Get a
getEnd Get a
getter) ByteString
bs
        forall (f :: * -> *) a. Applicative f => a -> f a
pure (SockAddr
addr, Either GetError a
ea)

datagramClientDecoder :: Maybe ByteCount -> NS.Socket -> Decoder ()
datagramClientDecoder :: Maybe ByteCount -> Socket -> Decoder ()
datagramClientDecoder Maybe ByteCount
mayLim Socket
sock =
  let lim :: Int
lim = forall b a. b -> (a -> b) -> Maybe a -> b
maybe Int
maxRecv ByteCount -> Int
unByteCount Maybe ByteCount
mayLim
  in  forall k.
(forall a. Get a -> IO (k, Either GetError a)) -> Decoder k
Decoder forall a b. (a -> b) -> a -> b
$ \Get a
getter -> do
        ByteString
bs <- Socket -> Int -> IO ByteString
NSB.recv Socket
sock Int
lim
        (Either GetError a
ea, ByteCount
_) <- forall z (m :: * -> *) a.
BinaryGetTarget z m =>
Get a -> z -> m (Either GetError a, ByteCount)
getTarget (forall a. Get a -> Get a
getEnd Get a
getter) ByteString
bs
        forall (f :: * -> *) a. Applicative f => a -> f a
pure ((), Either GetError a
ea)

newtype Encoder k = Encoder {forall k. Encoder k -> k -> Put -> IO ()
unEncoder :: k -> Put -> IO ()}

runEncoder :: (Binary a) => Encoder k -> k -> a -> IO ()
runEncoder :: forall a k. Binary a => Encoder k -> k -> a -> IO ()
runEncoder Encoder k
enc k
k = forall k. Encoder k -> k -> Put -> IO ()
unEncoder Encoder k
enc k
k forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Binary a => a -> Put
put

streamEncoder :: NS.Socket -> Encoder ()
streamEncoder :: Socket -> Encoder ()
streamEncoder Socket
sock = forall k. (k -> Put -> IO ()) -> Encoder k
Encoder (\()
_ -> forall z (m :: * -> *). BinaryPutTarget z m => Put -> m z
putTarget forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> Socket -> ByteString -> IO ()
NSB.sendAll Socket
sock)

datagramClientEncoder :: NS.Socket -> Encoder ()
datagramClientEncoder :: Socket -> Encoder ()
datagramClientEncoder Socket
sock = forall k. (k -> Put -> IO ()) -> Encoder k
Encoder (\()
_ -> forall z (m :: * -> *). BinaryPutTarget z m => Put -> m z
putTarget forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> Socket -> ByteString -> IO ()
NSB.sendAll Socket
sock)

datagramServerEncoder :: NS.Socket -> Encoder NS.SockAddr
datagramServerEncoder :: Socket -> Encoder SockAddr
datagramServerEncoder Socket
sock = forall k. (k -> Put -> IO ()) -> Encoder k
Encoder (\SockAddr
addr -> forall z (m :: * -> *). BinaryPutTarget z m => Put -> m z
putTarget forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> forall a b c. (a -> b -> c) -> b -> a -> c
flip (Socket -> ByteString -> SockAddr -> IO ()
NSB.sendAllTo Socket
sock) SockAddr
addr)

data Conn k = Conn {forall k. Conn k -> Decoder k
connDecoder :: Decoder k, forall k. Conn k -> Encoder k
connEncoder :: Encoder k}

data HostPort = HostPort
  { HostPort -> Maybe String
hpHost :: !(Maybe String)
  , HostPort -> Int
hpPort :: !Int
  }
  deriving stock (HostPort -> HostPort -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: HostPort -> HostPort -> Bool
$c/= :: HostPort -> HostPort -> Bool
== :: HostPort -> HostPort -> Bool
$c== :: HostPort -> HostPort -> Bool
Eq, Eq HostPort
HostPort -> HostPort -> Bool
HostPort -> HostPort -> Ordering
HostPort -> HostPort -> HostPort
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 :: HostPort -> HostPort -> HostPort
$cmin :: HostPort -> HostPort -> HostPort
max :: HostPort -> HostPort -> HostPort
$cmax :: HostPort -> HostPort -> HostPort
>= :: HostPort -> HostPort -> Bool
$c>= :: HostPort -> HostPort -> Bool
> :: HostPort -> HostPort -> Bool
$c> :: HostPort -> HostPort -> Bool
<= :: HostPort -> HostPort -> Bool
$c<= :: HostPort -> HostPort -> Bool
< :: HostPort -> HostPort -> Bool
$c< :: HostPort -> HostPort -> Bool
compare :: HostPort -> HostPort -> Ordering
$ccompare :: HostPort -> HostPort -> Ordering
Ord, Int -> HostPort -> ShowS
[HostPort] -> ShowS
HostPort -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [HostPort] -> ShowS
$cshowList :: [HostPort] -> ShowS
show :: HostPort -> String
$cshow :: HostPort -> String
showsPrec :: Int -> HostPort -> ShowS
$cshowsPrec :: Int -> HostPort -> ShowS
Show)

newtype TcpOpts = TcpOpts {TcpOpts -> Int
tcoFinTimeoutMs :: Int}
  deriving newtype (Int -> TcpOpts -> ShowS
[TcpOpts] -> ShowS
TcpOpts -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TcpOpts] -> ShowS
$cshowList :: [TcpOpts] -> ShowS
show :: TcpOpts -> String
$cshow :: TcpOpts -> String
showsPrec :: Int -> TcpOpts -> ShowS
$cshowsPrec :: Int -> TcpOpts -> ShowS
Show)
  deriving stock (TcpOpts -> TcpOpts -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TcpOpts -> TcpOpts -> Bool
$c/= :: TcpOpts -> TcpOpts -> Bool
== :: TcpOpts -> TcpOpts -> Bool
$c== :: TcpOpts -> TcpOpts -> Bool
Eq, Eq TcpOpts
TcpOpts -> TcpOpts -> Bool
TcpOpts -> TcpOpts -> Ordering
TcpOpts -> TcpOpts -> TcpOpts
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 :: TcpOpts -> TcpOpts -> TcpOpts
$cmin :: TcpOpts -> TcpOpts -> TcpOpts
max :: TcpOpts -> TcpOpts -> TcpOpts
$cmax :: TcpOpts -> TcpOpts -> TcpOpts
>= :: TcpOpts -> TcpOpts -> Bool
$c>= :: TcpOpts -> TcpOpts -> Bool
> :: TcpOpts -> TcpOpts -> Bool
$c> :: TcpOpts -> TcpOpts -> Bool
<= :: TcpOpts -> TcpOpts -> Bool
$c<= :: TcpOpts -> TcpOpts -> Bool
< :: TcpOpts -> TcpOpts -> Bool
$c< :: TcpOpts -> TcpOpts -> Bool
compare :: TcpOpts -> TcpOpts -> Ordering
$ccompare :: TcpOpts -> TcpOpts -> Ordering
Ord)

data SockTy = SockTyTcp | SockTyUdp
  deriving stock (SockTy -> SockTy -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SockTy -> SockTy -> Bool
$c/= :: SockTy -> SockTy -> Bool
== :: SockTy -> SockTy -> Bool
$c== :: SockTy -> SockTy -> Bool
Eq, Eq SockTy
SockTy -> SockTy -> Bool
SockTy -> SockTy -> Ordering
SockTy -> SockTy -> SockTy
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 :: SockTy -> SockTy -> SockTy
$cmin :: SockTy -> SockTy -> SockTy
max :: SockTy -> SockTy -> SockTy
$cmax :: SockTy -> SockTy -> SockTy
>= :: SockTy -> SockTy -> Bool
$c>= :: SockTy -> SockTy -> Bool
> :: SockTy -> SockTy -> Bool
$c> :: SockTy -> SockTy -> Bool
<= :: SockTy -> SockTy -> Bool
$c<= :: SockTy -> SockTy -> Bool
< :: SockTy -> SockTy -> Bool
$c< :: SockTy -> SockTy -> Bool
compare :: SockTy -> SockTy -> Ordering
$ccompare :: SockTy -> SockTy -> Ordering
Ord, Int -> SockTy -> ShowS
[SockTy] -> ShowS
SockTy -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SockTy] -> ShowS
$cshowList :: [SockTy] -> ShowS
show :: SockTy -> String
$cshow :: SockTy -> String
showsPrec :: Int -> SockTy -> ShowS
$cshowsPrec :: Int -> SockTy -> ShowS
Show, Int -> SockTy
SockTy -> Int
SockTy -> [SockTy]
SockTy -> SockTy
SockTy -> SockTy -> [SockTy]
SockTy -> SockTy -> SockTy -> [SockTy]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: SockTy -> SockTy -> SockTy -> [SockTy]
$cenumFromThenTo :: SockTy -> SockTy -> SockTy -> [SockTy]
enumFromTo :: SockTy -> SockTy -> [SockTy]
$cenumFromTo :: SockTy -> SockTy -> [SockTy]
enumFromThen :: SockTy -> SockTy -> [SockTy]
$cenumFromThen :: SockTy -> SockTy -> [SockTy]
enumFrom :: SockTy -> [SockTy]
$cenumFrom :: SockTy -> [SockTy]
fromEnum :: SockTy -> Int
$cfromEnum :: SockTy -> Int
toEnum :: Int -> SockTy
$ctoEnum :: Int -> SockTy
pred :: SockTy -> SockTy
$cpred :: SockTy -> SockTy
succ :: SockTy -> SockTy
$csucc :: SockTy -> SockTy
Enum, SockTy
forall a. a -> a -> Bounded a
maxBound :: SockTy
$cmaxBound :: SockTy
minBound :: SockTy
$cminBound :: SockTy
Bounded)

sockTyReal :: SockTy -> NS.SocketType
sockTyReal :: SockTy -> SocketType
sockTyReal = \case
  SockTy
SockTyTcp -> SocketType
NS.Stream
  SockTy
SockTyUdp -> SocketType
NS.Datagram

data Role = RoleServer | RoleClient
  deriving stock (Role -> Role -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Role -> Role -> Bool
$c/= :: Role -> Role -> Bool
== :: Role -> Role -> Bool
$c== :: Role -> Role -> Bool
Eq, Eq Role
Role -> Role -> Bool
Role -> Role -> Ordering
Role -> Role -> Role
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 :: Role -> Role -> Role
$cmin :: Role -> Role -> Role
max :: Role -> Role -> Role
$cmax :: Role -> Role -> Role
>= :: Role -> Role -> Bool
$c>= :: Role -> Role -> Bool
> :: Role -> Role -> Bool
$c> :: Role -> Role -> Bool
<= :: Role -> Role -> Bool
$c<= :: Role -> Role -> Bool
< :: Role -> Role -> Bool
$c< :: Role -> Role -> Bool
compare :: Role -> Role -> Ordering
$ccompare :: Role -> Role -> Ordering
Ord, Int -> Role -> ShowS
[Role] -> ShowS
Role -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Role] -> ShowS
$cshowList :: [Role] -> ShowS
show :: Role -> String
$cshow :: Role -> String
showsPrec :: Int -> Role -> ShowS
$cshowsPrec :: Int -> Role -> ShowS
Show)

data Target = Target
  { Target -> HostPort
targetHp :: !HostPort
  , Target -> SockTy
targetSockTy :: !SockTy
  , Target -> Role
targetRole :: !Role
  }
  deriving stock (Target -> Target -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Target -> Target -> Bool
$c/= :: Target -> Target -> Bool
== :: Target -> Target -> Bool
$c== :: Target -> Target -> Bool
Eq, Eq Target
Target -> Target -> Bool
Target -> Target -> Ordering
Target -> Target -> Target
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 :: Target -> Target -> Target
$cmin :: Target -> Target -> Target
max :: Target -> Target -> Target
$cmax :: Target -> Target -> Target
>= :: Target -> Target -> Bool
$c>= :: Target -> Target -> Bool
> :: Target -> Target -> Bool
$c> :: Target -> Target -> Bool
<= :: Target -> Target -> Bool
$c<= :: Target -> Target -> Bool
< :: Target -> Target -> Bool
$c< :: Target -> Target -> Bool
compare :: Target -> Target -> Ordering
$ccompare :: Target -> Target -> Ordering
Ord, Int -> Target -> ShowS
[Target] -> ShowS
Target -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Target] -> ShowS
$cshowList :: [Target] -> ShowS
show :: Target -> String
$cshow :: Target -> String
showsPrec :: Int -> Target -> ShowS
$cshowsPrec :: Int -> Target -> ShowS
Show)

resolveAddr :: HostPort -> IO NS.SockAddr
resolveAddr :: HostPort -> IO SockAddr
resolveAddr hp :: HostPort
hp@(HostPort Maybe String
host Int
port) = do
  [AddrInfo]
infos <- Maybe AddrInfo -> Maybe String -> Maybe String -> IO [AddrInfo]
NS.getAddrInfo forall a. Maybe a
Nothing Maybe String
host (forall a. a -> Maybe a
Just (forall a. Show a => a -> String
show Int
port))
  case [AddrInfo]
infos of
    [] -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String
"Could not resolve address: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show HostPort
hp)
    AddrInfo
info : [AddrInfo]
_ -> forall (f :: * -> *) a. Applicative f => a -> f a
pure (AddrInfo -> SockAddr
NS.addrAddress AddrInfo
info)

targetResolve :: Target -> IO NS.AddrInfo
targetResolve :: Target -> IO AddrInfo
targetResolve (Target hp :: HostPort
hp@(HostPort Maybe String
host Int
port) SockTy
sockTy Role
role) = do
  let hints :: AddrInfo
hints =
        AddrInfo
NS.defaultHints
          { addrSocketType :: SocketType
NS.addrSocketType = SockTy -> SocketType
sockTyReal SockTy
sockTy
          , addrFlags :: [AddrInfoFlag]
NS.addrFlags = [AddrInfoFlag
NS.AI_PASSIVE | Role
role forall a. Eq a => a -> a -> Bool
== Role
RoleServer]
          }
  [AddrInfo]
infos <- Maybe AddrInfo -> Maybe String -> Maybe String -> IO [AddrInfo]
NS.getAddrInfo (forall a. a -> Maybe a
Just AddrInfo
hints) Maybe String
host (forall a. a -> Maybe a
Just (forall a. Show a => a -> String
show Int
port))
  case [AddrInfo]
infos of
    [] -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String
"Could not resolve address: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show HostPort
hp)
    AddrInfo
info : [AddrInfo]
_ -> forall (f :: * -> *) a. Applicative f => a -> f a
pure AddrInfo
info

targetOpen :: Target -> IO (NS.Socket, NS.SockAddr)
targetOpen :: Target -> IO (Socket, SockAddr)
targetOpen Target
t = do
  AddrInfo
info <- Target -> IO AddrInfo
targetResolve Target
t
  Socket
sock <- AddrInfo -> IO Socket
NS.openSocket AddrInfo
info
  forall (f :: * -> *) a. Applicative f => a -> f a
pure (Socket
sock, AddrInfo -> SockAddr
NS.addrAddress AddrInfo
info)

targetConnect :: Target -> IO (NS.Socket, NS.SockAddr)
targetConnect :: Target -> IO (Socket, SockAddr)
targetConnect Target
t = do
  p :: (Socket, SockAddr)
p@(Socket
sock, SockAddr
addr) <- Target -> IO (Socket, SockAddr)
targetOpen Target
t
  Socket -> SockAddr -> IO ()
NS.connect Socket
sock SockAddr
addr
  forall (f :: * -> *) a. Applicative f => a -> f a
pure (Socket, SockAddr)
p

targetBind :: Target -> IO NS.Socket
targetBind :: Target -> IO Socket
targetBind Target
t = do
  (Socket
sock, SockAddr
addr) <- Target -> IO (Socket, SockAddr)
targetOpen Target
t
  Socket -> SocketOption -> Int -> IO ()
NS.setSocketOption Socket
sock SocketOption
NS.ReuseAddr Int
1
  forall r. Socket -> (CInt -> IO r) -> IO r
NS.withFdSocket Socket
sock CInt -> IO ()
NS.setCloseOnExecIfNeeded
  Socket -> SockAddr -> IO ()
NS.bind Socket
sock SockAddr
addr
  forall (f :: * -> *) a. Applicative f => a -> f a
pure Socket
sock

tcpClientSock :: HostPort -> TcpOpts -> Acquire (NS.SockAddr, NS.Socket)
tcpClientSock :: HostPort -> TcpOpts -> Acquire (SockAddr, Socket)
tcpClientSock HostPort
hp (TcpOpts Int
finTo) = forall a. IO a -> (a -> IO ()) -> Acquire a
mkAcquire IO (SockAddr, Socket)
acq (SockAddr, Socket) -> IO ()
rel
 where
  acq :: IO (SockAddr, Socket)
acq = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (a, b) -> (b, a)
swap (Target -> IO (Socket, SockAddr)
targetConnect (HostPort -> SockTy -> Role -> Target
Target HostPort
hp SockTy
SockTyTcp Role
RoleClient))
  rel :: (SockAddr, Socket) -> IO ()
rel (SockAddr
_, Socket
sock) = if Int
finTo forall a. Ord a => a -> a -> Bool
> Int
0 then Socket -> Int -> IO ()
NS.gracefulClose Socket
sock Int
finTo else Socket -> IO ()
NS.close Socket
sock

tcpClientConn :: Maybe ByteCount -> HostPort -> TcpOpts -> Acquire (NS.SockAddr, Conn ())
tcpClientConn :: Maybe ByteCount
-> HostPort -> TcpOpts -> Acquire (SockAddr, Conn ())
tcpClientConn Maybe ByteCount
mayLim HostPort
hp TcpOpts
to = do
  (SockAddr
addr, Socket
sock) <- HostPort -> TcpOpts -> Acquire (SockAddr, Socket)
tcpClientSock HostPort
hp TcpOpts
to
  Decoder ()
dec <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Maybe ByteCount -> Socket -> IO (Decoder ())
streamDecoder Maybe ByteCount
mayLim Socket
sock)
  let enc :: Encoder ()
enc = Socket -> Encoder ()
streamEncoder Socket
sock
  forall (f :: * -> *) a. Applicative f => a -> f a
pure (SockAddr
addr, forall k. Decoder k -> Encoder k -> Conn k
Conn Decoder ()
dec Encoder ()
enc)

withTcpClientConn :: (MonadUnliftIO m) => Maybe ByteCount -> HostPort -> TcpOpts -> (NS.SockAddr -> Conn () -> m a) -> m a
withTcpClientConn :: forall (m :: * -> *) a.
MonadUnliftIO m =>
Maybe ByteCount
-> HostPort -> TcpOpts -> (SockAddr -> Conn () -> m a) -> m a
withTcpClientConn Maybe ByteCount
mayLim HostPort
hp TcpOpts
to = forall (m :: * -> *) a b.
MonadUnliftIO m =>
Acquire a -> (a -> m b) -> m b
withAcquire (Maybe ByteCount
-> HostPort -> TcpOpts -> Acquire (SockAddr, Conn ())
tcpClientConn Maybe ByteCount
mayLim HostPort
hp TcpOpts
to) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry

tcpServerSock :: HostPort -> Acquire NS.Socket
tcpServerSock :: HostPort -> Acquire Socket
tcpServerSock HostPort
hp = forall a. IO a -> (a -> IO ()) -> Acquire a
mkAcquire IO Socket
acq Socket -> IO ()
rel
 where
  acq :: IO Socket
acq = do
    Socket
sock <- Target -> IO Socket
targetBind (HostPort -> SockTy -> Role -> Target
Target HostPort
hp SockTy
SockTyTcp Role
RoleServer)
    Socket -> Int -> IO ()
NS.listen Socket
sock Int
maxQueue
    forall (f :: * -> *) a. Applicative f => a -> f a
pure Socket
sock
  rel :: Socket -> IO ()
rel = Socket -> IO ()
NS.close

tcpServerConn :: Maybe ByteCount -> HostPort -> TcpOpts -> Acquire (Acquire (NS.SockAddr, Conn ()))
tcpServerConn :: Maybe ByteCount
-> HostPort -> TcpOpts -> Acquire (Acquire (SockAddr, Conn ()))
tcpServerConn Maybe ByteCount
mayLim HostPort
hp TcpOpts
to = do
  Socket
srvSock <- HostPort -> Acquire Socket
tcpServerSock HostPort
hp
  forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ do
    (SockAddr
addr, Socket
cliSock) <- TcpOpts -> Socket -> Acquire (SockAddr, Socket)
tcpAcceptSock TcpOpts
to Socket
srvSock
    Decoder ()
dec <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Maybe ByteCount -> Socket -> IO (Decoder ())
streamDecoder Maybe ByteCount
mayLim Socket
cliSock)
    let enc :: Encoder ()
enc = Socket -> Encoder ()
streamEncoder Socket
cliSock
    forall (f :: * -> *) a. Applicative f => a -> f a
pure (SockAddr
addr, forall k. Decoder k -> Encoder k -> Conn k
Conn Decoder ()
dec Encoder ()
enc)

tcpAcceptSock :: TcpOpts -> NS.Socket -> Acquire (NS.SockAddr, NS.Socket)
tcpAcceptSock :: TcpOpts -> Socket -> Acquire (SockAddr, Socket)
tcpAcceptSock (TcpOpts Int
finTo) Socket
servSock = forall a. IO a -> (a -> IO ()) -> Acquire a
mkAcquire IO (SockAddr, Socket)
acq (SockAddr, Socket) -> IO ()
rel
 where
  acq :: IO (SockAddr, Socket)
acq = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (a, b) -> (b, a)
swap (Socket -> IO (Socket, SockAddr)
NS.accept Socket
servSock)
  rel :: (SockAddr, Socket) -> IO ()
rel (SockAddr
_, Socket
sock) = if Int
finTo forall a. Ord a => a -> a -> Bool
> Int
0 then Socket -> Int -> IO ()
NS.gracefulClose Socket
sock Int
finTo else Socket -> IO ()
NS.close Socket
sock

udpClientSock :: HostPort -> Acquire (NS.SockAddr, NS.Socket)
udpClientSock :: HostPort -> Acquire (SockAddr, Socket)
udpClientSock HostPort
hp = forall a. IO a -> (a -> IO ()) -> Acquire a
mkAcquire IO (SockAddr, Socket)
acq forall {a}. (a, Socket) -> IO ()
rel
 where
  acq :: IO (SockAddr, Socket)
acq = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (a, b) -> (b, a)
swap (Target -> IO (Socket, SockAddr)
targetConnect (HostPort -> SockTy -> Role -> Target
Target HostPort
hp SockTy
SockTyUdp Role
RoleClient))
  rel :: (a, Socket) -> IO ()
rel = Socket -> IO ()
NS.close forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd

udpClientConn :: Maybe ByteCount -> HostPort -> Acquire (NS.SockAddr, Conn ())
udpClientConn :: Maybe ByteCount -> HostPort -> Acquire (SockAddr, Conn ())
udpClientConn Maybe ByteCount
mayLim HostPort
hp = do
  (SockAddr
addr, Socket
sock) <- HostPort -> Acquire (SockAddr, Socket)
udpClientSock HostPort
hp
  let dec :: Decoder ()
dec = Maybe ByteCount -> Socket -> Decoder ()
datagramClientDecoder Maybe ByteCount
mayLim Socket
sock
      enc :: Encoder ()
enc = Socket -> Encoder ()
datagramClientEncoder Socket
sock
  forall (f :: * -> *) a. Applicative f => a -> f a
pure (SockAddr
addr, forall k. Decoder k -> Encoder k -> Conn k
Conn Decoder ()
dec Encoder ()
enc)

withUdpClientConn :: (MonadUnliftIO m) => Maybe ByteCount -> HostPort -> (NS.SockAddr -> Conn () -> m a) -> m a
withUdpClientConn :: forall (m :: * -> *) a.
MonadUnliftIO m =>
Maybe ByteCount -> HostPort -> (SockAddr -> Conn () -> m a) -> m a
withUdpClientConn Maybe ByteCount
mayLim HostPort
hp = forall (m :: * -> *) a b.
MonadUnliftIO m =>
Acquire a -> (a -> m b) -> m b
withAcquire (Maybe ByteCount -> HostPort -> Acquire (SockAddr, Conn ())
udpClientConn Maybe ByteCount
mayLim HostPort
hp) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry

udpServerSock :: HostPort -> Acquire NS.Socket
udpServerSock :: HostPort -> Acquire Socket
udpServerSock HostPort
hp = forall a. IO a -> (a -> IO ()) -> Acquire a
mkAcquire IO Socket
acq Socket -> IO ()
rel
 where
  acq :: IO Socket
acq = Target -> IO Socket
targetBind (HostPort -> SockTy -> Role -> Target
Target HostPort
hp SockTy
SockTyUdp Role
RoleServer)
  rel :: Socket -> IO ()
rel = Socket -> IO ()
NS.close

udpServerConn :: Maybe ByteCount -> HostPort -> Acquire (Conn NS.SockAddr)
udpServerConn :: Maybe ByteCount -> HostPort -> Acquire (Conn SockAddr)
udpServerConn Maybe ByteCount
mayLim HostPort
hp = do
  Socket
sock <- HostPort -> Acquire Socket
udpServerSock HostPort
hp
  let dec :: Decoder SockAddr
dec = Maybe ByteCount -> Socket -> Decoder SockAddr
datagramServerDecoder Maybe ByteCount
mayLim Socket
sock
      enc :: Encoder SockAddr
enc = Socket -> Encoder SockAddr
datagramServerEncoder Socket
sock
  forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall k. Decoder k -> Encoder k -> Conn k
Conn Decoder SockAddr
dec Encoder SockAddr
enc)

withUdpServerConn :: (MonadUnliftIO m) => Maybe ByteCount -> HostPort -> (Conn NS.SockAddr -> m a) -> m a
withUdpServerConn :: forall (m :: * -> *) a.
MonadUnliftIO m =>
Maybe ByteCount -> HostPort -> (Conn SockAddr -> m a) -> m a
withUdpServerConn Maybe ByteCount
mayLim HostPort
hp = forall (m :: * -> *) a b.
MonadUnliftIO m =>
Acquire a -> (a -> m b) -> m b
withAcquire (Maybe ByteCount -> HostPort -> Acquire (Conn SockAddr)
udpServerConn Maybe ByteCount
mayLim HostPort
hp)