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 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
$ \Ptr ()
_ Ptr C'netcode_address_t
aptr Ptr Word8
pkt 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 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
$ \Ptr ()
_ Ptr C'netcode_address_t
aptr Ptr Word8
pkt 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