{-# LINE 1 "Z/IO/Network/SocketAddr.hsc" #-}
module Z.IO.Network.SocketAddr
(
SocketAddr(..)
, ipv4, ipv6
, sockAddrFamily
, withSocketAddr
, withSocketAddrUnsafe
, sizeOfSocketAddr
, withSocketAddrStorage
, withSocketAddrStorageUnsafe
, sizeOfSocketAddrStorage
, InetAddr(..)
, inetAny
, inetBroadcast
, inetNone
, inetLoopback
, inetUnspecificGroup
, inetAllHostsGroup
, inetMaxLocalGroup
, inetAddrToTuple
, tupleToInetAddr
, Inet6Addr(..)
, inet6Any
, inet6Loopback
, inet6AddrToTuple
, tupleToInet6Addr
, FlowInfo
, ScopeID
, PortNumber(..)
, portAny
, SocketFamily
, pattern AF_UNSPEC
, pattern AF_INET
, pattern AF_INET6
, SocketType
, pattern SOCK_DGRAM
, pattern SOCK_STREAM
, pattern SOCK_SEQPACKET
, pattern SOCK_RAW
, pattern SOCK_RDM
, pattern SOCK_ANY
, ProtocolNumber
, pattern IPPROTO_DEFAULT
, pattern IPPROTO_IP
, pattern IPPROTO_TCP
, pattern IPPROTO_UDP
, peekSocketAddr
, pokeSocketAddr
, peekSocketAddrMBA
, pokeSocketAddrMBA
, htons
, ntohs
, ntohl
, htonl
) where
import Data.Bits
import qualified Data.List as List
import Data.Typeable
import Foreign
import Foreign.C
import GHC.Generics
import Numeric (showHex)
import System.IO.Unsafe
import Z.Data.CBytes
import Z.Data.Text.ShowT (ShowT)
import Z.IO.Exception
import Z.IO.UV.Errno
import Z.Foreign
{-# LINE 95 "Z/IO/Network/SocketAddr.hsc" #-}
{-# LINE 97 "Z/IO/Network/SocketAddr.hsc" #-}
{-# LINE 105 "Z/IO/Network/SocketAddr.hsc" #-}
type CSaFamily = (Word16)
{-# LINE 106 "Z/IO/Network/SocketAddr.hsc" #-}
{-# LINE 107 "Z/IO/Network/SocketAddr.hsc" #-}
data SocketAddr
= SocketAddrInet
{-# UNPACK #-} !PortNumber
{-# UNPACK #-} !InetAddr
| SocketAddrInet6
{-# UNPACK #-} !PortNumber
{-# UNPACK #-} !FlowInfo
{-# UNPACK #-} !Inet6Addr
{-# UNPACK #-} !ScopeID
deriving (Eq, Ord, Typeable)
instance Show SocketAddr where
showsPrec _ (SocketAddrInet port ia)
= shows ia . showString ":" . shows port
showsPrec _ (SocketAddrInet6 port _ ia6 _)
= ('[':) . shows ia6 . showString "]:" . shows port
sockAddrFamily :: SocketAddr -> SocketFamily
sockAddrFamily (SocketAddrInet _ _) = AF_INET
sockAddrFamily (SocketAddrInet6 _ _ _ _) = AF_INET6
type FlowInfo = Word32
type ScopeID = Word32
ipv4:: HasCallStack => CBytes -> PortNumber -> SocketAddr
ipv4 str (PortNumber port) = unsafeDupablePerformIO . withSocketAddrStorageUnsafe $ \ p ->
withCBytesUnsafe str $ \ cstr -> throwUVIfMinus_ $ uv_ip4_addr cstr (fromIntegral port) p
ipv6:: HasCallStack => CBytes -> PortNumber -> SocketAddr
ipv6 str (PortNumber port) = unsafeDupablePerformIO . withSocketAddrStorageUnsafe $ \ p ->
withCBytesUnsafe str $ \ cstr -> throwUVIfMinus_ $ uv_ip6_addr cstr (fromIntegral port) p
newtype InetAddr = InetAddr { getInetAddr :: Word32 } deriving (Eq, Ord, Typeable)
instance Show InetAddr where
showsPrec _ ia =
let (a,b,c,d) = inetAddrToTuple ia
in shows a . ('.':) . shows b . ('.':) . shows c . ('.':) . shows d
inetAny :: InetAddr
inetAny = InetAddr 0
inetBroadcast :: InetAddr
inetBroadcast = tupleToInetAddr (255,255,255,255)
inetNone :: InetAddr
inetNone = tupleToInetAddr (255,255,255,255)
inetLoopback :: InetAddr
inetLoopback = tupleToInetAddr (127, 0, 0, 1)
inetUnspecificGroup :: InetAddr
inetUnspecificGroup = tupleToInetAddr (224, 0, 0, 0)
inetAllHostsGroup :: InetAddr
inetAllHostsGroup = tupleToInetAddr (224, 0, 0, 1)
inetMaxLocalGroup :: InetAddr
inetMaxLocalGroup = tupleToInetAddr (224, 0, 0,255)
instance Storable InetAddr where
sizeOf _ = 4
alignment _ = alignment (undefined :: Word32)
peek p = (InetAddr . ntohl) `fmap` peekByteOff p 0
poke p (InetAddr ia) = pokeByteOff p 0 (htonl ia)
instance Unaligned InetAddr where
unalignedSize _ = 4
pokeMBA p off x = pokeMBA p off (htonl (getInetAddr x))
peekMBA p off = InetAddr . ntohl <$> peekMBA p off
indexBA p off = InetAddr (ntohl (indexBA p off))
inetAddrToTuple :: InetAddr -> (Word8, Word8, Word8, Word8)
inetAddrToTuple (InetAddr ia) =
let byte i = fromIntegral (ia `shiftR` i) :: Word8
in (byte 24, byte 16, byte 8, byte 0)
tupleToInetAddr :: (Word8, Word8, Word8, Word8) -> InetAddr
tupleToInetAddr (b3, b2, b1, b0) =
let x `sl` i = fromIntegral x `shiftL` i :: Word32
in InetAddr $ (b3 `sl` 24) .|. (b2 `sl` 16) .|. (b1 `sl` 8) .|. (b0 `sl` 0)
data Inet6Addr = Inet6Addr {-# UNPACK #-}!Word32
{-# UNPACK #-}!Word32
{-# UNPACK #-}!Word32
{-# UNPACK #-}!Word32 deriving (Eq, Ord, Typeable)
instance Show Inet6Addr where
showsPrec _ ia6@(Inet6Addr a1 a2 a3 a4)
| a1 == 0 && a2 == 0 && a3 == 0xffff =
showString "::ffff:" . shows (InetAddr a4)
| a1 == 0 && a2 == 0 && a3 == 0 && a4 >= 0x10000 =
showString "::" . shows (InetAddr a4)
| end - begin > 1 =
showFields prefix . showString "::" . showFields suffix
| otherwise =
showFields fields
where
fields =
let (u7, u6, u5, u4, u3, u2, u1, u0) = inet6AddrToTuple ia6 in
[u7, u6, u5, u4, u3, u2, u1, u0]
showFields = foldr (.) id . List.intersperse (':':) . map showHex
prefix = take begin fields
suffix = drop end fields
begin = end + diff
(diff, end) = minimum $
scanl (\c i -> if i == 0 then c - 1 else 0) 0 fields `zip` [0..]
inet6Any :: Inet6Addr
inet6Any = Inet6Addr 0 0 0 0
inet6Loopback :: Inet6Addr
inet6Loopback = Inet6Addr 0 0 0 1
inet6AddrToTuple :: Inet6Addr -> (Word16, Word16, Word16, Word16,
Word16, Word16, Word16, Word16)
inet6AddrToTuple (Inet6Addr w3 w2 w1 w0) =
let high, low :: Word32 -> Word16
high w = fromIntegral (w `shiftR` 16)
low w = fromIntegral w
in (high w3, low w3, high w2, low w2, high w1, low w1, high w0, low w0)
tupleToInet6Addr :: (Word16, Word16, Word16, Word16,
Word16, Word16, Word16, Word16) -> Inet6Addr
tupleToInet6Addr (w7, w6, w5, w4, w3, w2, w1, w0) =
let add :: Word16 -> Word16 -> Word32
high `add` low = (fromIntegral high `shiftL` 16) .|. (fromIntegral low)
in Inet6Addr (w7 `add` w6) (w5 `add` w4) (w3 `add` w2) (w1 `add` w0)
instance Storable Inet6Addr where
sizeOf _ = (16)
{-# LINE 277 "Z/IO/Network/SocketAddr.hsc" #-}
alignment _ = 4
{-# LINE 278 "Z/IO/Network/SocketAddr.hsc" #-}
peek p = do
a <- peek32 p 0
b <- peek32 p 1
c <- peek32 p 2
d <- peek32 p 3
return $ Inet6Addr a b c d
poke p (Inet6Addr a b c d) = do
poke32 p 0 a
poke32 p 1 b
poke32 p 2 c
poke32 p 3 d
s6_addr_offset :: Int
s6_addr_offset = ((0))
{-# LINE 293 "Z/IO/Network/SocketAddr.hsc" #-}
peek32 :: Ptr a -> Int -> IO Word32
peek32 p i0 = do
let i' = i0 * 4
peekByte n = peekByteOff p (s6_addr_offset + i' + n) :: IO Word8
a `sl` i = fromIntegral a `shiftL` i
a0 <- peekByte 0
a1 <- peekByte 1
a2 <- peekByte 2
a3 <- peekByte 3
return ((a0 `sl` 24) .|. (a1 `sl` 16) .|. (a2 `sl` 8) .|. (a3 `sl` 0))
poke32 :: Ptr a -> Int -> Word32 -> IO ()
poke32 p i0 a = do
let i' = i0 * 4
pokeByte n = pokeByteOff p (s6_addr_offset + i' + n)
x `sr` i = fromIntegral (x `shiftR` i) :: Word8
pokeByte 0 (a `sr` 24)
pokeByte 1 (a `sr` 16)
pokeByte 2 (a `sr` 8)
pokeByte 3 (a `sr` 0)
instance Unaligned Inet6Addr where
unalignedSize _ = ((16))
{-# LINE 317 "Z/IO/Network/SocketAddr.hsc" #-}
indexBA p off =
let a = indexBA p (off + s6_addr_offset + 0)
b = indexBA p (off + s6_addr_offset + 4)
c = indexBA p (off + s6_addr_offset + 8)
d = indexBA p (off + s6_addr_offset + 12)
in Inet6Addr (getBE a) (getBE b) (getBE c) (getBE d)
peekMBA p off = do
a <- peekMBA p (off + s6_addr_offset + 0)
b <- peekMBA p (off + s6_addr_offset + 4)
c <- peekMBA p (off + s6_addr_offset + 8)
d <- peekMBA p (off + s6_addr_offset + 12)
return $ Inet6Addr (getBE a) (getBE b) (getBE c) (getBE d)
pokeMBA p off (Inet6Addr a b c d) = do
pokeMBA p (off + s6_addr_offset) (BE a)
pokeMBA p (off + 4 + s6_addr_offset) (BE b)
pokeMBA p (off + 8 + s6_addr_offset) (BE c)
pokeMBA p (off + 12 + s6_addr_offset) (BE d)
peekSocketAddr :: HasCallStack => Ptr SocketAddr -> IO SocketAddr
peekSocketAddr p = do
family <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) p
{-# LINE 343 "Z/IO/Network/SocketAddr.hsc" #-}
case family :: CSaFamily of
(2) -> do
{-# LINE 345 "Z/IO/Network/SocketAddr.hsc" #-}
addr <- ((\hsc_ptr -> peekByteOff hsc_ptr 4)) p
{-# LINE 346 "Z/IO/Network/SocketAddr.hsc" #-}
port <- ((\hsc_ptr -> peekByteOff hsc_ptr 2)) p
{-# LINE 347 "Z/IO/Network/SocketAddr.hsc" #-}
return (SocketAddrInet port addr)
(10) -> do
{-# LINE 349 "Z/IO/Network/SocketAddr.hsc" #-}
port <- ((\hsc_ptr -> peekByteOff hsc_ptr 2)) p
{-# LINE 350 "Z/IO/Network/SocketAddr.hsc" #-}
flow <- ((\hsc_ptr -> peekByteOff hsc_ptr 4)) p
{-# LINE 351 "Z/IO/Network/SocketAddr.hsc" #-}
addr <- ((\hsc_ptr -> peekByteOff hsc_ptr 8)) p
{-# LINE 352 "Z/IO/Network/SocketAddr.hsc" #-}
scope <- ((\hsc_ptr -> peekByteOff hsc_ptr 24)) p
{-# LINE 353 "Z/IO/Network/SocketAddr.hsc" #-}
return (SocketAddrInet6 port flow addr scope)
_ -> do let errno = UV_EAI_ADDRFAMILY
name <- uvErrName errno
desc <- uvStdError errno
throwUVError errno (IOEInfo name desc callStack)
pokeSocketAddr :: Ptr SocketAddr -> SocketAddr -> IO ()
pokeSocketAddr p (SocketAddrInet port addr) = do
{-# LINE 364 "Z/IO/Network/SocketAddr.hsc" #-}
{-# LINE 367 "Z/IO/Network/SocketAddr.hsc" #-}
((\hsc_ptr -> pokeByteOff hsc_ptr 0)) p ((2) :: CSaFamily)
{-# LINE 368 "Z/IO/Network/SocketAddr.hsc" #-}
((\hsc_ptr -> pokeByteOff hsc_ptr 2)) p port
{-# LINE 369 "Z/IO/Network/SocketAddr.hsc" #-}
((\hsc_ptr -> pokeByteOff hsc_ptr 4)) p addr
{-# LINE 370 "Z/IO/Network/SocketAddr.hsc" #-}
pokeSocketAddr p (SocketAddrInet6 port flow addr scope) = do
{-# LINE 374 "Z/IO/Network/SocketAddr.hsc" #-}
{-# LINE 377 "Z/IO/Network/SocketAddr.hsc" #-}
((\hsc_ptr -> pokeByteOff hsc_ptr 0)) p ((10) :: CSaFamily)
{-# LINE 378 "Z/IO/Network/SocketAddr.hsc" #-}
((\hsc_ptr -> pokeByteOff hsc_ptr 2)) p port
{-# LINE 379 "Z/IO/Network/SocketAddr.hsc" #-}
((\hsc_ptr -> pokeByteOff hsc_ptr 4)) p flow
{-# LINE 380 "Z/IO/Network/SocketAddr.hsc" #-}
((\hsc_ptr -> pokeByteOff hsc_ptr 8)) p (addr)
{-# LINE 381 "Z/IO/Network/SocketAddr.hsc" #-}
((\hsc_ptr -> pokeByteOff hsc_ptr 24)) p scope
{-# LINE 382 "Z/IO/Network/SocketAddr.hsc" #-}
withSocketAddr :: SocketAddr -> (Ptr SocketAddr -> IO a) -> IO a
withSocketAddr sa@(SocketAddrInet _ _) f = do
allocaBytesAligned
((16))
{-# LINE 390 "Z/IO/Network/SocketAddr.hsc" #-}
(4) $ \ p -> pokeSocketAddr p sa >> f p
{-# LINE 391 "Z/IO/Network/SocketAddr.hsc" #-}
withSocketAddr sa@(SocketAddrInet6 _ _ _ _) f = do
allocaBytesAligned
((28))
{-# LINE 394 "Z/IO/Network/SocketAddr.hsc" #-}
(4) $ \ p -> pokeSocketAddr p sa >> f p
{-# LINE 395 "Z/IO/Network/SocketAddr.hsc" #-}
withSocketAddrUnsafe :: SocketAddr -> (MBA# SocketAddr -> IO a) -> IO a
withSocketAddrUnsafe sa@(SocketAddrInet _ _) f = do
(MutableByteArray p) <- newByteArray ((16))
{-# LINE 403 "Z/IO/Network/SocketAddr.hsc" #-}
pokeSocketAddrMBA p sa
f p
withSocketAddrUnsafe sa@(SocketAddrInet6 _ _ _ _) f = do
(MutableByteArray p) <- newByteArray ((28))
{-# LINE 407 "Z/IO/Network/SocketAddr.hsc" #-}
pokeSocketAddrMBA p sa
f p
sizeOfSocketAddr :: SocketAddr -> CSize
sizeOfSocketAddr (SocketAddrInet _ _) = (16)
{-# LINE 412 "Z/IO/Network/SocketAddr.hsc" #-}
sizeOfSocketAddr (SocketAddrInet6 _ _ _ _) = (28)
{-# LINE 413 "Z/IO/Network/SocketAddr.hsc" #-}
withSocketAddrStorage :: (Ptr SocketAddr -> IO ()) -> IO SocketAddr
withSocketAddrStorage f = do
allocaBytesAligned
((128))
{-# LINE 419 "Z/IO/Network/SocketAddr.hsc" #-}
(8) $ \ p -> f p >> peekSocketAddr p
{-# LINE 420 "Z/IO/Network/SocketAddr.hsc" #-}
withSocketAddrStorageUnsafe :: (MBA# SocketAddr -> IO ()) -> IO SocketAddr
withSocketAddrStorageUnsafe f = do
(MutableByteArray p) <- newByteArray ((128))
{-# LINE 428 "Z/IO/Network/SocketAddr.hsc" #-}
f p
peekSocketAddrMBA p
sizeOfSocketAddrStorage :: CSize
sizeOfSocketAddrStorage = ((128))
{-# LINE 433 "Z/IO/Network/SocketAddr.hsc" #-}
peekSocketAddrMBA :: HasCallStack => MBA# SocketAddr -> IO SocketAddr
peekSocketAddrMBA p = do
family <- peekMBA p ((0))
{-# LINE 437 "Z/IO/Network/SocketAddr.hsc" #-}
case family :: CSaFamily of
(2) -> do
{-# LINE 439 "Z/IO/Network/SocketAddr.hsc" #-}
addr <- peekMBA p ((4))
{-# LINE 440 "Z/IO/Network/SocketAddr.hsc" #-}
port <- peekMBA p ((2))
{-# LINE 441 "Z/IO/Network/SocketAddr.hsc" #-}
return (SocketAddrInet port addr)
(10) -> do
{-# LINE 443 "Z/IO/Network/SocketAddr.hsc" #-}
port <- peekMBA p ((2))
{-# LINE 444 "Z/IO/Network/SocketAddr.hsc" #-}
flow <- peekMBA p ((4))
{-# LINE 445 "Z/IO/Network/SocketAddr.hsc" #-}
addr <- peekMBA p ((8))
{-# LINE 446 "Z/IO/Network/SocketAddr.hsc" #-}
scope <- peekMBA p ((24))
{-# LINE 447 "Z/IO/Network/SocketAddr.hsc" #-}
return (SocketAddrInet6 port flow addr scope)
_ -> do let errno = UV_EAI_ADDRFAMILY
name <- uvErrName errno
desc <- uvStdError errno
throwUVError errno (IOEInfo name desc callStack)
pokeSocketAddrMBA :: MBA# SocketAddr -> SocketAddr -> IO ()
pokeSocketAddrMBA p (SocketAddrInet port addr) = do
{-# LINE 458 "Z/IO/Network/SocketAddr.hsc" #-}
{-# LINE 461 "Z/IO/Network/SocketAddr.hsc" #-}
pokeMBA p ((0)) ((2) :: CSaFamily)
{-# LINE 462 "Z/IO/Network/SocketAddr.hsc" #-}
pokeMBA p ((2)) port
{-# LINE 463 "Z/IO/Network/SocketAddr.hsc" #-}
pokeMBA p ((4)) addr
{-# LINE 464 "Z/IO/Network/SocketAddr.hsc" #-}
pokeSocketAddrMBA p (SocketAddrInet6 port flow addr scope) = do
{-# LINE 468 "Z/IO/Network/SocketAddr.hsc" #-}
{-# LINE 471 "Z/IO/Network/SocketAddr.hsc" #-}
pokeMBA p ((0)) ((10) :: CSaFamily)
{-# LINE 472 "Z/IO/Network/SocketAddr.hsc" #-}
pokeMBA p ((2)) port
{-# LINE 473 "Z/IO/Network/SocketAddr.hsc" #-}
pokeMBA p ((4)) flow
{-# LINE 474 "Z/IO/Network/SocketAddr.hsc" #-}
pokeMBA p ((8)) (addr)
{-# LINE 475 "Z/IO/Network/SocketAddr.hsc" #-}
pokeMBA p ((24)) scope
{-# LINE 476 "Z/IO/Network/SocketAddr.hsc" #-}
newtype PortNumber = PortNumber Word16 deriving (Eq, Ord, Enum, Generic)
deriving newtype (Show, Read, Num, Bounded, Real, Integral)
deriving anyclass ShowT
portAny :: PortNumber
portAny = PortNumber 0
instance Storable PortNumber where
sizeOf _ = sizeOf (0 :: Word16)
alignment _ = alignment (0 :: Word16)
poke p (PortNumber po) = poke (castPtr p) (htons po)
peek p = PortNumber . ntohs <$> peek (castPtr p)
instance Unaligned PortNumber where
unalignedSize _ = 2
indexBA p off = PortNumber . ntohs $ indexBA p off
pokeMBA p off (PortNumber po) = pokeMBA p off (htons po)
peekMBA p off = PortNumber . ntohs <$> peekMBA p off
type SocketFamily = CInt
type SocketType = CInt
type ProtocolNumber = CInt
pattern AF_UNSPEC :: SocketFamily
pattern AF_UNSPEC = 0
{-# LINE 525 "Z/IO/Network/SocketAddr.hsc" #-}
pattern AF_INET :: SocketFamily
pattern AF_INET = 2
{-# LINE 528 "Z/IO/Network/SocketAddr.hsc" #-}
pattern AF_INET6 :: SocketFamily
pattern AF_INET6 = 10
{-# LINE 531 "Z/IO/Network/SocketAddr.hsc" #-}
pattern SOCK_STREAM :: SocketType
pattern SOCK_STREAM = 1
{-# LINE 534 "Z/IO/Network/SocketAddr.hsc" #-}
pattern SOCK_DGRAM :: SocketType
pattern SOCK_DGRAM = 2
{-# LINE 536 "Z/IO/Network/SocketAddr.hsc" #-}
pattern SOCK_RAW :: SocketType
pattern SOCK_RAW = 3
{-# LINE 538 "Z/IO/Network/SocketAddr.hsc" #-}
pattern SOCK_RDM :: SocketType
pattern SOCK_RDM = 4
{-# LINE 540 "Z/IO/Network/SocketAddr.hsc" #-}
pattern SOCK_SEQPACKET :: SocketType
pattern SOCK_SEQPACKET = 5
{-# LINE 542 "Z/IO/Network/SocketAddr.hsc" #-}
pattern SOCK_ANY :: SocketType
pattern SOCK_ANY = 0
pattern IPPROTO_DEFAULT :: ProtocolNumber
pattern IPPROTO_DEFAULT = 0
pattern IPPROTO_IP :: ProtocolNumber
pattern IPPROTO_IP = 0
{-# LINE 550 "Z/IO/Network/SocketAddr.hsc" #-}
pattern IPPROTO_TCP :: ProtocolNumber
pattern IPPROTO_TCP = 6
{-# LINE 552 "Z/IO/Network/SocketAddr.hsc" #-}
pattern IPPROTO_UDP :: ProtocolNumber
pattern IPPROTO_UDP = 17
{-# LINE 554 "Z/IO/Network/SocketAddr.hsc" #-}
foreign import ccall unsafe "ntohs" ntohs :: Word16 -> Word16
{-# LINE 558 "Z/IO/Network/SocketAddr.hsc" #-}
foreign import ccall unsafe "htons" htons :: Word16 -> Word16
{-# LINE 559 "Z/IO/Network/SocketAddr.hsc" #-}
foreign import ccall unsafe "ntohl" ntohl :: Word32 -> Word32
{-# LINE 560 "Z/IO/Network/SocketAddr.hsc" #-}
foreign import ccall unsafe "htonl" htonl :: Word32 -> Word32
{-# LINE 561 "Z/IO/Network/SocketAddr.hsc" #-}
foreign import ccall unsafe uv_ip4_addr :: BA# Word8 -> CInt -> MBA# SocketAddr -> IO CInt
foreign import ccall unsafe uv_ip6_addr :: BA# Word8 -> CInt -> MBA# SocketAddr -> IO CInt