{-# LINE 1 "Z/IO/Network/SocketAddr.hsc" #-}
{-|
Module      : Z.IO.Network.SocketAddr
Description : TCP\/UDP socket address API
Copyright   : (c) Winterland, 2018
License     : BSD
Maintainer  : drkoster@qq.com
Stability   : experimental
Portability : non-portable

This module provides necessary types and constant for low level socket address manipulating.

-}

module Z.IO.Network.SocketAddr
  ( -- * name to address
    SocketAddr(..)
  , ipv4, ipv6
  , sockAddrFamily
  , withSocketAddr
  , withSocketAddrUnsafe
  , sizeOfSocketAddr
  , withSocketAddrStorage
  , withSocketAddrStorageUnsafe
  , sizeOfSocketAddrStorage
   -- ** IPv4 address
  , InetAddr(..)
  , inetAny
  , inetBroadcast
  , inetNone
  , inetLoopback
  , inetUnspecificGroup
  , inetAllHostsGroup
  , inetMaxLocalGroup
  , inetAddrToTuple
  , tupleToInetAddr
   -- ** IPv6 address
  , Inet6Addr(..)
  , inet6Any
  , inet6Loopback
  , inet6AddrToTuple
  , tupleToInet6Addr
  , FlowInfo
  , ScopeID
  -- * port numbber
  , PortNumber(..)
  , portAny
  -- * family, type, protocol
  -- ** SocketFamily
  , 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
  -- * Internal helper
  , 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" #-}

-- | IPv4 or IPv6 socket address, i.e. the `sockaddr_in` or `sockaddr_in6` struct.
-- 
data SocketAddr
    = SocketAddrInet
        {-# UNPACK #-} !PortNumber  -- sin_port  (network byte order)
        {-# UNPACK #-} !InetAddr    -- sin_addr  (ditto)
    | SocketAddrInet6
        {-# UNPACK #-} !PortNumber  -- sin6_port (network byte order)
        {-# UNPACK #-} !FlowInfo    -- sin6_flowinfo (ditto)
        {-# UNPACK #-} !Inet6Addr   -- sin6_addr (ditto)
        {-# UNPACK #-} !ScopeID     -- sin6_scope_id (ditto)
  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

-- | Convert a string containing an IPv4 addresses to a binary structure
--
-- This is partial function, wrong address will throw 'InvalidArgument' exception.
ipv4:: HasCallStack => CBytes -> PortNumber -> SocketAddr
ipv4 str (PortNumber port) = unsafeDupablePerformIO . withSocketAddrStorageUnsafe $ \ p ->
    withCBytesUnsafe str $ \ cstr -> throwUVIfMinus_ $ uv_ip4_addr cstr (fromIntegral port) p

-- | Convert a string containing an IPv6 addresses to a binary structure
--
-- This is partial function, wrong address will throw 'InvalidArgument' exception.
ipv6:: HasCallStack => CBytes -> PortNumber -> SocketAddr
ipv6 str (PortNumber port) = unsafeDupablePerformIO . withSocketAddrStorageUnsafe $ \ p ->
    withCBytesUnsafe str $ \ cstr -> throwUVIfMinus_ $ uv_ip6_addr cstr (fromIntegral port) p

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

-- | Independent of endianness. For example @127.0.0.1@ is stored as @(127, 0, 0, 1)@.
--
-- For direct manipulation prefer 'inetAddrToTuple' and 'tupleToInetAddr'.
--
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

-- | @0.0.0.0@
inetAny             :: InetAddr
inetAny              = InetAddr 0

-- | @255.255.255.255@
inetBroadcast       :: InetAddr
inetBroadcast        = tupleToInetAddr (255,255,255,255)

-- | @255.255.255.255@
inetNone            :: InetAddr
inetNone             = tupleToInetAddr (255,255,255,255)

-- | @127.0.0.1@
inetLoopback        :: InetAddr
inetLoopback         = tupleToInetAddr (127,  0,  0,  1)

-- | @224.0.0.0@
inetUnspecificGroup :: InetAddr
inetUnspecificGroup  = tupleToInetAddr (224,  0,  0,  0)

-- | @224.0.0.1@
inetAllHostsGroup   :: InetAddr
inetAllHostsGroup    = tupleToInetAddr (224,  0,  0,  1)

-- | @224.0.0.255@
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))

-- | Converts 'InetAddr' to representation-independent IPv4 quadruple.
-- For example for @127.0.0.1@ the function will return @(127, 0, 0, 1)@
-- regardless of host endianness.
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)

-- | Converts IPv4 quadruple to 'InetAddr'.
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)

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

-- | Independent of endianness. For example @::1@ is stored as @(0, 0, 0, 1)@.
--
-- For direct manipulation prefer 'inet6AddrToTuple' and 'tupleToInet6Addr'.
--
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)
        -- IPv4-Mapped IPv6 Address
        | a1 == 0 && a2 == 0 && a3 == 0xffff =
          showString "::ffff:" . shows (InetAddr a4)
        -- IPv4-Compatible IPv6 Address (exclude IPRange ::/112)
        | a1 == 0 && a2 == 0 && a3 == 0 && a4 >= 0x10000 =
            showString "::" . shows (InetAddr a4)
        -- length of longest run > 1, replace it with "::"
        | 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  -- fields before "::"
        suffix = drop end fields    -- fields after "::"
        begin = end + diff          -- the longest run of zeros
        (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

-- | @::1@
inet6Loopback :: Inet6Addr
inet6Loopback  = Inet6Addr 0 0 0 1

-- | convert 'Inet6Addr' to octets.
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)

-- | convert 'Inet6Addr' from octets.
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" #-}


-- | Pass 'SocketAddr' to FFI as pointer.
--
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" #-}

-- | Pass 'SocketAddr' to FFI as pointer.
--
-- USE THIS FUNCTION WITH UNSAFE FFI CALL ONLY.
--
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" #-}

-- | Allocate space for 'sockaddr_storage' and pass to FFI.
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" #-}

-- | Allocate space for 'sockaddr_storage' and pass to FFI.
--
-- USE THIS FUNCTION WITH UNSAFE FFI CALL ONLY.
--
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" #-}

--------------------------------------------------------------------------------
-- Port Numbers

-- | Port number.
--   Use the @Num@ instance (i.e. use a literal) to create a
--   @PortNumber@ value.
--
-- >>> 1 :: PortNumber
-- 1
-- >>> read "1" :: PortNumber
-- 1
-- >>> show (12345 :: PortNumber)
-- "12345"
-- >>> 50000 < (51000 :: PortNumber)
-- True
-- >>> 50000 < (52000 :: PortNumber)
-- True
-- >>> 50000 + (10000 :: PortNumber)
-- 60000
newtype PortNumber = PortNumber Word16 deriving (Eq, Ord, Enum, Generic)
                                        deriving newtype (Show, Read, Num, Bounded, Real, Integral)
                                        deriving anyclass ShowT

-- | @:0@
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

-- | unspecified
pattern AF_UNSPEC :: SocketFamily
pattern AF_UNSPEC = 0
{-# LINE 525 "Z/IO/Network/SocketAddr.hsc" #-}
-- | internetwork: UDP, TCP, etc
pattern AF_INET :: SocketFamily
pattern AF_INET = 2
{-# LINE 528 "Z/IO/Network/SocketAddr.hsc" #-}
-- | Internet Protocol version 6
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" #-}
-- | Used in getAddrInfo hints, for any type can be returned by getAddrInfo
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