{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE StandaloneDeriving #-} {-# OPTIONS_GHC -Wno-orphans #-} module Protocol.Base.Internal.Network ( PortNumber , IpAddr4 , IpAddr6 , FlowInfo , ScopeID , IpAddr(..) , EcnCodepoint(..) , ecnFromBits , SockAddr4(..) , SockAddr6(..) , SockAddr(..) , addrIsPort0 ) where -- external import Codec.Serialise (Serialise) import Data.Binary (Binary) import Data.Bits import Data.ByteString (ByteString) import Data.WideWord import Data.Word import GHC.Generics (Generic) -- TODO upstream these deriving instance Binary Word128 deriving instance Serialise Word128 -- all the following types represent byte-sequences in network-order i.e. big-endian type PortNumber = Word16 type IpAddr4 = Word32 type IpAddr6 = Word128 type FlowInfo = Word32 type ScopeID = Word32 data IpAddr = IpAddr4 !IpAddr4 | IpAddr6 !IpAddr6 deriving (Show, Read, Generic, Binary, Serialise, Eq, Ord) data EcnCodepoint = NotECT | ECT1 | ECT0 | CE deriving (Show, Read, Generic, Binary, Serialise, Eq, Ord, Enum, Bounded) ecnFromBits :: Integral a => a -> Maybe EcnCodepoint ecnFromBits x = case fromIntegral x .&. 0x03 :: Word8 of 1 -> Just ECT1 2 -> Just ECT0 3 -> Just CE _ -> Nothing data SockAddr4 = SockAddr4 { ipAddr4 :: !IpAddr4 , portNum :: !PortNumber } deriving (Show, Read, Generic, Binary, Serialise, Eq, Ord) data SockAddr6 = SockAddr6 { ipAddr6 :: !IpAddr6 , portNum :: !PortNumber , flowInfo :: !FlowInfo , scopeId :: !ScopeID } deriving (Show, Read, Generic, Binary, Serialise, Eq, Ord) data SockAddr = SockAddrInet4 !SockAddr4 | SockAddrInet6 !SockAddr6 | SockAddrUnix !ByteString deriving (Show, Read, Generic, Binary, Serialise, Eq, Ord) addrIsPort0 :: SockAddr -> Bool addrIsPort0 addr = case addr of SockAddrInet4 (SockAddr4 _ p ) -> p == 0 SockAddrInet6 (SockAddr6 _ p _ _) -> p == 0 SockAddrUnix _ -> False