{-# OPTIONS_GHC -optc-D_GNU_SOURCE #-}
{-# LINE 1 "src/Linux/Socket/Types.hsc" #-}
{-# language DataKinds #-}
{-# language DerivingStrategies #-}
{-# language DuplicateRecordFields #-}
{-# language GeneralizedNewtypeDeriving #-}
{-# language BinaryLiterals #-}
{-# language TypeApplications #-}

-- This is needed because hsc2hs does not currently handle ticked
-- promoted data constructors correctly.
{-# OPTIONS_GHC -fno-warn-unticked-promoted-constructors #-}









-- | All of the data constructors provided by this module are unsafe.
--   Only use them if you really know what you are doing.
module Linux.Socket.Types
  ( SocketFlags(..)
  , dontWait
  , truncate
  , controlTruncate
  , closeOnExec
  , nonblocking
  , headerInclude
    -- * Multiple Message Header
  , pokeMultipleMessageHeaderName
  , pokeMultipleMessageHeaderNameLength
  , pokeMultipleMessageHeaderIOVector
  , pokeMultipleMessageHeaderIOVectorLength
  , pokeMultipleMessageHeaderControl
  , pokeMultipleMessageHeaderControlLength
  , pokeMultipleMessageHeaderFlags
  , pokeMultipleMessageHeaderLength
  , peekMultipleMessageHeaderLength
  , peekMultipleMessageHeaderNameLength
  , sizeofMultipleMessageHeader
    -- * UDP Header
  , sizeofUdpHeader
  , pokeUdpHeaderSourcePort
  , pokeUdpHeaderDestinationPort
  , pokeUdpHeaderLength
  , pokeUdpHeaderChecksum
    -- * IPv4 Header
  , sizeofIpHeader
  , pokeIpHeaderVersionIhl
  , pokeIpHeaderTypeOfService
  , pokeIpHeaderTotalLength
  , pokeIpHeaderIdentifier
  , pokeIpHeaderFragmentOffset
  , pokeIpHeaderTimeToLive
  , pokeIpHeaderProtocol
  , pokeIpHeaderChecksum
  , pokeIpHeaderSourceAddress
  , pokeIpHeaderDestinationAddress
  ) where

import Prelude hiding (truncate)

import Data.Bits (Bits((.|.)))
import Data.Word (Word8,Word16,Word32)
import Data.Primitive.Addr (Addr(..),writeOffAddr)
import Foreign.C.Types (CInt(..),CSize,CUInt)
import Posix.Socket (MessageFlags(..),Message(Receive),OptionName(..))
import Foreign.Storable (peekByteOff,pokeByteOff)
import GHC.Ptr (Ptr(..))

newtype SocketFlags = SocketFlags CInt
  deriving stock (Eq)
  deriving newtype (Bits)

-- newtype Collection :: Type -> Type where
--   Collection :: !(Ptr a) -> Collection a
-- 
-- indexCollection :: Ptr a
--   => Collection a -> Int -> IO (Ptr a)
-- indexCollection (Collection p) n = advancePtr p n
-- data MessageHeader = MessageHeader
--   { name :: !Addr
--   , nameLength :: !CInt
--   , vector :: !(Ptr InputOutputVector)
--   , vectorLength :: !CSize
--   , control :: !(Ptr ControlMessageHeader)
--   , controlLength :: !CSize
--   , flags :: !(MessageFlags Receive)
--   }
-- 
-- data IOVector = IOVector
--   { base :: !Addr
--   , length :: !CSize
--   }
-- 
-- data ControlMessageHeader = ControlMessageHeader
--   { length :: !CInt
--   , level :: !CInt
--   , type_ :: !CInt
--   , data_ :: !Addr
--   }

instance Semigroup SocketFlags where (<>) = (.|.)
instance Monoid SocketFlags where mempty = SocketFlags 0

-- | The @MSG_DONTWAIT@ receive flag or send flag.
dontWait :: MessageFlags m
dontWait = MessageFlags 64
{-# LINE 110 "src/Linux/Socket/Types.hsc" #-}

-- | The @MSG_TRUNC@ receive flag.
truncate :: MessageFlags Receive
truncate = MessageFlags 32
{-# LINE 114 "src/Linux/Socket/Types.hsc" #-}

-- | The @MSG_CTRUNC@ receive flag.
controlTruncate :: MessageFlags Receive
controlTruncate = MessageFlags 8
{-# LINE 118 "src/Linux/Socket/Types.hsc" #-}

-- | The @SOCK_CLOEXEC@ receive flag or send flag.
closeOnExec :: SocketFlags
closeOnExec = SocketFlags 524288
{-# LINE 122 "src/Linux/Socket/Types.hsc" #-}

-- | The @SOCK_NONBLOCK@ receive flag or send flag.
nonblocking :: SocketFlags
nonblocking = SocketFlags 2048
{-# LINE 126 "src/Linux/Socket/Types.hsc" #-}

-- | If enabled, the user supplies an IP header in front of the
-- user data.  Valid only for @SOCK_RAW@ sockets.
headerInclude :: OptionName
headerInclude = OptionName 3
{-# LINE 131 "src/Linux/Socket/Types.hsc" #-}

-- | The size of a @mmsghdr@ struct.
sizeofMultipleMessageHeader :: CInt
sizeofMultipleMessageHeader = (64)
{-# LINE 135 "src/Linux/Socket/Types.hsc" #-}

pokeMultipleMessageHeaderName :: Addr -> Addr -> IO ()
pokeMultipleMessageHeaderName (Addr p) (Addr x) = (\hsc_ptr -> pokeByteOff hsc_ptr 0) (Ptr p) (Ptr x)
{-# LINE 138 "src/Linux/Socket/Types.hsc" #-}

pokeMultipleMessageHeaderNameLength :: Addr -> CInt -> IO ()
pokeMultipleMessageHeaderNameLength (Addr p) = (\hsc_ptr -> pokeByteOff hsc_ptr 8) (Ptr p)
{-# LINE 141 "src/Linux/Socket/Types.hsc" #-}

pokeMultipleMessageHeaderIOVector :: Addr -> Addr -> IO ()
pokeMultipleMessageHeaderIOVector (Addr p) (Addr x) = (\hsc_ptr -> pokeByteOff hsc_ptr 16) (Ptr p) (Ptr x)
{-# LINE 144 "src/Linux/Socket/Types.hsc" #-}

pokeMultipleMessageHeaderIOVectorLength :: Addr -> CSize -> IO ()
pokeMultipleMessageHeaderIOVectorLength (Addr p) = (\hsc_ptr -> pokeByteOff hsc_ptr 24) (Ptr p)
{-# LINE 147 "src/Linux/Socket/Types.hsc" #-}

pokeMultipleMessageHeaderControl :: Addr -> Addr -> IO ()
pokeMultipleMessageHeaderControl (Addr p) (Addr x) = (\hsc_ptr -> pokeByteOff hsc_ptr 32) (Ptr p) (Ptr x)
{-# LINE 150 "src/Linux/Socket/Types.hsc" #-}

pokeMultipleMessageHeaderControlLength :: Addr -> CSize -> IO ()
pokeMultipleMessageHeaderControlLength (Addr p) = (\hsc_ptr -> pokeByteOff hsc_ptr 40) (Ptr p)
{-# LINE 153 "src/Linux/Socket/Types.hsc" #-}

pokeMultipleMessageHeaderFlags :: Addr -> MessageFlags Receive -> IO ()
pokeMultipleMessageHeaderFlags (Addr p) (MessageFlags i) = (\hsc_ptr -> pokeByteOff hsc_ptr 48) (Ptr p) i
{-# LINE 156 "src/Linux/Socket/Types.hsc" #-}

pokeMultipleMessageHeaderLength :: Addr -> CUInt -> IO ()
pokeMultipleMessageHeaderLength (Addr p) i = (\hsc_ptr -> pokeByteOff hsc_ptr 56) (Ptr p) i
{-# LINE 159 "src/Linux/Socket/Types.hsc" #-}

peekMultipleMessageHeaderNameLength :: Addr -> IO CInt
peekMultipleMessageHeaderNameLength (Addr p) = (\hsc_ptr -> peekByteOff hsc_ptr 8) (Ptr p)
{-# LINE 162 "src/Linux/Socket/Types.hsc" #-}

peekMultipleMessageHeaderLength :: Addr -> IO CUInt
peekMultipleMessageHeaderLength (Addr p) = (\hsc_ptr -> peekByteOff hsc_ptr 56) (Ptr p)
{-# LINE 165 "src/Linux/Socket/Types.hsc" #-}

-- | The size of a @udphdr@ struct.
sizeofUdpHeader :: CInt
sizeofUdpHeader = (8)
{-# LINE 169 "src/Linux/Socket/Types.hsc" #-}

pokeUdpHeaderSourcePort :: Addr -> Word16 -> IO ()
pokeUdpHeaderSourcePort (Addr p) = (\hsc_ptr -> pokeByteOff hsc_ptr 0) (Ptr p)
{-# LINE 172 "src/Linux/Socket/Types.hsc" #-}

pokeUdpHeaderDestinationPort :: Addr -> Word16 -> IO ()
pokeUdpHeaderDestinationPort (Addr p) = (\hsc_ptr -> pokeByteOff hsc_ptr 2) (Ptr p)
{-# LINE 175 "src/Linux/Socket/Types.hsc" #-}

pokeUdpHeaderLength :: Addr -> Word16 -> IO ()
pokeUdpHeaderLength (Addr p) = (\hsc_ptr -> pokeByteOff hsc_ptr 4) (Ptr p)
{-# LINE 178 "src/Linux/Socket/Types.hsc" #-}

pokeUdpHeaderChecksum :: Addr -> Word16 -> IO ()
pokeUdpHeaderChecksum (Addr p) = (\hsc_ptr -> pokeByteOff hsc_ptr 6) (Ptr p)
{-# LINE 181 "src/Linux/Socket/Types.hsc" #-}

-- | The size of an @iphdr@ struct.
sizeofIpHeader :: CInt
sizeofIpHeader = (20)
{-# LINE 185 "src/Linux/Socket/Types.hsc" #-}

-- | This poke function requires the user to pack the version and the
-- internet header length (IHL), each 4 bits, into a single 8-bit word.
-- The version should be in the most significant bits. This function
-- will marshal the value appropriately depending on the platform's
-- bit-endianness.
pokeIpHeaderVersionIhl :: Addr -> Word8 -> IO ()
-- TODO: Verify if this is correct. Also, something bad is going
-- on here. Fix this.

{-# LINE 195 "src/Linux/Socket/Types.hsc" #-}
pokeIpHeaderVersionIhl p _ = writeOffAddr p 0 (0b01000101 :: Word8)

{-# LINE 201 "src/Linux/Socket/Types.hsc" #-}

pokeIpHeaderTypeOfService :: Addr -> Word8 -> IO ()
pokeIpHeaderTypeOfService (Addr p) = (\hsc_ptr -> pokeByteOff hsc_ptr 1) (Ptr p)
{-# LINE 204 "src/Linux/Socket/Types.hsc" #-}

pokeIpHeaderTotalLength :: Addr -> Word16 -> IO ()
pokeIpHeaderTotalLength (Addr p) = (\hsc_ptr -> pokeByteOff hsc_ptr 2) (Ptr p)
{-# LINE 207 "src/Linux/Socket/Types.hsc" #-}

pokeIpHeaderIdentifier :: Addr -> Word16 -> IO ()
pokeIpHeaderIdentifier (Addr p) = (\hsc_ptr -> pokeByteOff hsc_ptr 4) (Ptr p)
{-# LINE 210 "src/Linux/Socket/Types.hsc" #-}

pokeIpHeaderFragmentOffset :: Addr -> Word16 -> IO ()
pokeIpHeaderFragmentOffset (Addr p) = (\hsc_ptr -> pokeByteOff hsc_ptr 6) (Ptr p)
{-# LINE 213 "src/Linux/Socket/Types.hsc" #-}

pokeIpHeaderTimeToLive :: Addr -> Word8 -> IO ()
pokeIpHeaderTimeToLive (Addr p) = (\hsc_ptr -> pokeByteOff hsc_ptr 8) (Ptr p)
{-# LINE 216 "src/Linux/Socket/Types.hsc" #-}

pokeIpHeaderProtocol :: Addr -> Word8 -> IO ()
pokeIpHeaderProtocol (Addr p) = (\hsc_ptr -> pokeByteOff hsc_ptr 9) (Ptr p)
{-# LINE 219 "src/Linux/Socket/Types.hsc" #-}

pokeIpHeaderChecksum :: Addr -> Word16 -> IO ()
pokeIpHeaderChecksum (Addr p) = (\hsc_ptr -> pokeByteOff hsc_ptr 10) (Ptr p)
{-# LINE 222 "src/Linux/Socket/Types.hsc" #-}

pokeIpHeaderSourceAddress :: Addr -> Word32 -> IO ()
pokeIpHeaderSourceAddress (Addr p) = (\hsc_ptr -> pokeByteOff hsc_ptr 12) (Ptr p)
{-# LINE 225 "src/Linux/Socket/Types.hsc" #-}

pokeIpHeaderDestinationAddress :: Addr -> Word32 -> IO ()
pokeIpHeaderDestinationAddress (Addr p) = (\hsc_ptr -> pokeByteOff hsc_ptr 16) (Ptr p)
{-# LINE 228 "src/Linux/Socket/Types.hsc" #-}