module Netcode.IO.Callbacks where

-------------------------------------------------------------------------------

import Data.Word             (Word8)
import Foreign.C.Types       (CInt)
import Foreign.ForeignPtr    (newForeignPtr_)
import Foreign.Ptr           (Ptr)

import Bindings.Netcode.IO
import Netcode.IO.Address

-------------------------------------------------------------------------------


-- | Override that sends a packet to the given address. This can be used by

-- both clients and servers. This is invoked after @netcode.io@ processes and

-- encrypts the packet.

type SendPacketOverride
     = Address    -- ^ 'Address' to send the packet to

    -> Ptr Word8  -- ^ A pointer to the memory that holds the packet data

    -> CInt       -- ^ The size of the packet

    -> IO ()

mkSendPacketOverride :: SendPacketOverride -> IO C'send_packet_override_t
mkSendPacketOverride :: SendPacketOverride -> IO C'send_packet_override_t
mkSendPacketOverride sendFn :: SendPacketOverride
sendFn =
    (Ptr () -> Ptr C'netcode_address_t -> Ptr Word8 -> CInt -> IO ())
-> IO C'send_packet_override_t
mk'send_packet_override_t ((Ptr () -> Ptr C'netcode_address_t -> Ptr Word8 -> CInt -> IO ())
 -> IO C'send_packet_override_t)
-> (Ptr ()
    -> Ptr C'netcode_address_t -> Ptr Word8 -> CInt -> IO ())
-> IO C'send_packet_override_t
forall a b. (a -> b) -> a -> b
$ \_ aptr :: Ptr C'netcode_address_t
aptr pkt :: Ptr Word8
pkt pktSize :: CInt
pktSize -> do
        Address
addr <- ForeignPtr C'netcode_address_t -> Address
Address (ForeignPtr C'netcode_address_t -> Address)
-> IO (ForeignPtr C'netcode_address_t) -> IO Address
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr C'netcode_address_t -> IO (ForeignPtr C'netcode_address_t)
forall a. Ptr a -> IO (ForeignPtr a)
newForeignPtr_ Ptr C'netcode_address_t
aptr
        SendPacketOverride
sendFn Address
addr Ptr Word8
pkt CInt
pktSize

-- | Override that receives a packet from the given address. This can be used

-- by both clients and servers. This is invoked before @netcode.io@ processes

-- and decrypts the packet data.

--

-- Implementations of this callback are meant to fill the memory at the given

-- pointer with the data from a packet received from the 'Address'. The maximum

-- size of the buffer pointed to is also passed and the implementation is

-- expected to return the actual size of the packet. In the event that there is

-- no packet (or equivalently, no packet data), then the implementation should

-- return zero.

type ReceivePacketOverride
     = Address    -- ^ Address from which to receive a packet

    -> Ptr Word8  -- ^ Pointer to the buffer where to write packet data

    -> CInt       -- ^ Maximum size of destination buffer in bytes

    -> IO CInt    -- ^ Return value: should be size of packet data


mkReceivePacketOverride :: ReceivePacketOverride
                        -> IO C'receive_packet_override_t
mkReceivePacketOverride :: ReceivePacketOverride -> IO C'receive_packet_override_t
mkReceivePacketOverride recvFn :: ReceivePacketOverride
recvFn =
    (Ptr () -> Ptr C'netcode_address_t -> Ptr Word8 -> CInt -> IO CInt)
-> IO C'receive_packet_override_t
mk'receive_packet_override_t ((Ptr ()
  -> Ptr C'netcode_address_t -> Ptr Word8 -> CInt -> IO CInt)
 -> IO C'receive_packet_override_t)
-> (Ptr ()
    -> Ptr C'netcode_address_t -> Ptr Word8 -> CInt -> IO CInt)
-> IO C'receive_packet_override_t
forall a b. (a -> b) -> a -> b
$ \_ aptr :: Ptr C'netcode_address_t
aptr pkt :: Ptr Word8
pkt pktSize :: CInt
pktSize -> do
        Address
addr <- ForeignPtr C'netcode_address_t -> Address
Address (ForeignPtr C'netcode_address_t -> Address)
-> IO (ForeignPtr C'netcode_address_t) -> IO Address
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr C'netcode_address_t -> IO (ForeignPtr C'netcode_address_t)
forall a. Ptr a -> IO (ForeignPtr a)
newForeignPtr_ Ptr C'netcode_address_t
aptr
        ReceivePacketOverride
recvFn Address
addr Ptr Word8
pkt CInt
pktSize