{-# LINE 1 "src/Simplex/Chat/Remote/Multicast.hsc" #-}
module Simplex.Chat.Remote.Multicast (setMembership) where

import Foreign (Ptr, allocaBytes, castPtr, pokeByteOff)
import Foreign.C.Types (CInt (..))
import Network.Socket



-- | Toggle multicast group membership.
-- NB: Group membership is per-host, not per-process. A socket is only used to access system interface for groups.
setMembership :: Socket -> HostAddress -> Bool -> IO (Either CInt ())
setMembership :: Socket -> HostAddress -> Bool -> IO (Either CInt ())
setMembership Socket
sock HostAddress
group Bool
membership = Int -> (Ptr Any -> IO (Either CInt ())) -> IO (Either CInt ())
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes (Int
8) ((Ptr Any -> IO (Either CInt ())) -> IO (Either CInt ()))
-> (Ptr Any -> IO (Either CInt ())) -> IO (Either CInt ())
forall a b. (a -> b) -> a -> b
$ \Ptr Any
mReqPtr -> do
{-# LINE 13 "src/Simplex/Chat/Remote/Multicast.hsc" #-}
  (\hsc_ptr -> pokeByteOff hsc_ptr 0) mReqPtr group
{-# LINE 14 "src/Simplex/Chat/Remote/Multicast.hsc" #-}
  (\hsc_ptr -> pokeByteOff hsc_ptr 4) mReqPtr (0 :: HostAddress) -- attempt to contact the group on ANY interface
{-# LINE 15 "src/Simplex/Chat/Remote/Multicast.hsc" #-}
  withFdSocket sock $ \fd -> do
    rc <- c_setsockopt fd c_IPPROTO_IP flag (castPtr mReqPtr) ((8))
{-# LINE 17 "src/Simplex/Chat/Remote/Multicast.hsc" #-}
    if rc == 0
      then pure $ Right ()
      else pure $ Left rc
  where
    flag :: CInt
flag = if Bool
membership then CInt
c_IP_ADD_MEMBERSHIP else CInt
c_IP_DROP_MEMBERSHIP


{-# LINE 33 "src/Simplex/Chat/Remote/Multicast.hsc" #-}

foreign import ccall unsafe "setsockopt"
    c_setsockopt :: CInt -> CInt -> CInt -> Ptr CInt -> CInt -> IO CInt

c_IP_ADD_MEMBERSHIP, c_IP_DROP_MEMBERSHIP :: CInt
c_IP_ADD_MEMBERSHIP :: CInt
c_IP_ADD_MEMBERSHIP  = CInt
35
{-# LINE 39 "src/Simplex/Chat/Remote/Multicast.hsc" #-}
c_IP_DROP_MEMBERSHIP = 36
{-# LINE 40 "src/Simplex/Chat/Remote/Multicast.hsc" #-}


{-# LINE 42 "src/Simplex/Chat/Remote/Multicast.hsc" #-}

c_IPPROTO_IP :: CInt
c_IPPROTO_IP :: CInt
c_IPPROTO_IP = CInt
0
{-# LINE 45 "src/Simplex/Chat/Remote/Multicast.hsc" #-}