{-# language BangPatterns #-}
{-# language DataKinds #-}
{-# language DuplicateRecordFields #-}
{-# language GADTSyntax #-}
{-# language KindSignatures #-}
{-# language LambdaCase #-}
{-# language MagicHash #-}
{-# language NamedFieldPuns #-}
module Socket.Datagram.Uninterruptible.Bytes
(
send
, sendToIPv4
, receive
, receiveFromIPv4
, receiveMany
, receiveManyFromIPv4
, Message(..)
, Peer(..)
, ReceiveException(..)
, PeerlessSlab(..)
, IPv4Slab(..)
, newPeerlessSlab
, newIPv4Slab
) where
import Data.Bytes.Types (Bytes,MutableBytes(..))
import Data.Primitive (ByteArray,SmallArray)
import Data.Primitive.Unlifted.Array (UnliftedArray)
import Data.Primitive.PrimArray.Offset (MutablePrimArrayOffset(..))
import GHC.Exts (proxy#)
import Socket (Connectedness(..),Family(..),Version(..),Interruptibility(Uninterruptible))
import Socket.Address (posixToIPv4Peer)
import Socket.Datagram (Socket(..),SendException,ReceiveException(..))
import Socket.IPv4 (Peer(..),Message(..),IPv4Slab(..),freezeIPv4Slab)
import Socket.IPv4 (newIPv4Slab)
import Socket.Discard (PeerlessSlab(..),newPeerlessSlab)
import qualified Data.Primitive as PM
import qualified Socket.Discard
import qualified Socket.Datagram.Uninterruptible.Bytes.Send.Connected as CS
import qualified Socket.Datagram.Uninterruptible.Bytes.Send.IPv4 as V4S
import qualified Socket.Datagram.Uninterruptible.MutableBytes.Many as MM
import qualified Socket.Datagram.Uninterruptible.MutableBytes.Receive.Connected as CR
import qualified Socket.Datagram.Uninterruptible.MutableBytes.Receive.IPv4 as V4R
send ::
Socket 'Connected a
-> Bytes
-> IO (Either (SendException 'Uninterruptible) ())
send (Socket !sock) !buf =
CS.send proxy# () sock buf
sendToIPv4 ::
Socket 'Unconnected ('Internet 'V4)
-> Peer
-> Bytes
-> IO (Either (SendException 'Uninterruptible) ())
sendToIPv4 (Socket !sock) !dst !buf =
V4S.send proxy# dst sock buf
receive ::
Socket c a
-> Int
-> IO (Either (ReceiveException 'Uninterruptible) ByteArray)
receive (Socket !sock) !maxSz = do
buf <- PM.newByteArray maxSz
CR.receive proxy# sock (MutableBytes buf 0 maxSz) () >>= \case
Right sz -> do
r <- PM.resizeMutableByteArray buf sz >>= PM.unsafeFreezeByteArray
pure (Right r)
Left err -> pure (Left err)
receiveFromIPv4 ::
Socket 'Unconnected ('Internet 'V4)
-> Int
-> IO (Either (ReceiveException 'Uninterruptible) Message)
receiveFromIPv4 (Socket !sock) !maxSz = do
buf <- PM.newByteArray maxSz
addr <- PM.newPrimArray 1
V4R.receive proxy# sock (MutableBytes buf 0 maxSz) (MutablePrimArrayOffset addr 0) >>= \case
Right size -> do
r <- PM.resizeMutableByteArray buf size >>= PM.unsafeFreezeByteArray
posixAddr <- PM.readPrimArray addr 0
pure (Right (Message (posixToIPv4Peer posixAddr) r))
Left err -> pure (Left err)
receiveManyFromIPv4 ::
Socket 'Unconnected ('Internet 'V4)
-> Socket.IPv4.IPv4Slab
-> IO (Either (ReceiveException 'Uninterruptible) (SmallArray Message))
receiveManyFromIPv4 sock slab = do
MM.receiveManyFromIPv4 sock slab >>= \case
Left err -> pure (Left err)
Right n -> do
arr <- Socket.IPv4.freezeIPv4Slab slab n
pure (Right arr)
receiveMany ::
Socket 'Unconnected ('Internet 'V4)
-> Socket.Discard.PeerlessSlab
-> IO (Either (ReceiveException 'Uninterruptible) (UnliftedArray ByteArray))
receiveMany sock slab = do
MM.receiveMany sock slab >>= \case
Left err -> pure (Left err)
Right n -> do
arr <- Socket.Discard.freezePeerlessSlab slab n
pure (Right arr)