quic-0.1.21: Network/QUIC/Types/Packet.hs
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}
module Network.QUIC.Types.Packet where
import Codec.Serialise
import Data.Ix
import GHC.Generics
import Network.TLS.QUIC (ExtensionID (EID_QuicTransportParameters, ExtensionID))
import Network.UDP
import Text.Printf
import Network.QUIC.Imports
import Network.QUIC.Types.Ack
import Network.QUIC.Types.CID
import Network.QUIC.Types.Frame
import Network.QUIC.Types.Time
----------------------------------------------------------------
-- | QUIC version.
newtype Version = Version Word32 deriving (Eq, Ord, Generic)
instance Serialise Version
{- FOURMOLU_DISABLE -}
pattern Negotiation :: Version
pattern Negotiation = Version 0
pattern Version1 :: Version
pattern Version1 = Version 1
pattern Version2 :: Version
pattern Version2 = Version 0x6b3343cf
pattern Draft29 :: Version
pattern Draft29 = Version 0xff00001d
pattern GreasingVersion :: Version
pattern GreasingVersion = Version 0x0a0a0a0a
pattern GreasingVersion2 :: Version
pattern GreasingVersion2 = Version 0x1a2a3a4a
instance Show Version where
show (Version 0) = "Negotiation"
show (Version 1) = "Version1"
show (Version 0x6b3343cf) = "Version2"
show (Version 0xff00001d) = "Draft29"
show ver@(Version v)
| isGreasingVersion ver = "Greasing 0x" ++ printf "%08x" v
| otherwise = "Version 0x" ++ printf "%08x" v
{- FOURMOLU_ENABLE -}
isGreasingVersion :: Version -> Bool
isGreasingVersion (Version v) = v .&. 0x0a0a0a0a == 0x0a0a0a0a
----------------------------------------------------------------
data VersionInfo = VersionInfo
{ chosenVersion :: Version
, otherVersions :: [Version]
}
deriving (Eq, Show)
brokenVersionInfo :: VersionInfo
brokenVersionInfo = VersionInfo Negotiation []
----------------------------------------------------------------
extensionIDForTtransportParameter :: Version -> ExtensionID
extensionIDForTtransportParameter Version1 = EID_QuicTransportParameters
extensionIDForTtransportParameter Version2 = EID_QuicTransportParameters
extensionIDForTtransportParameter _ = ExtensionID 0xffa5
----------------------------------------------------------------
data PacketI
= PacketIV VersionNegotiationPacket
| PacketIR RetryPacket
| PacketIC CryptPacket EncryptionLevel Int
| PacketIB BrokenPacket Int
deriving (Eq, Show)
-- Not used internally. Only for 'encodePacket'.
data PacketO
= PacketOV VersionNegotiationPacket
| PacketOR RetryPacket
| PacketOP PlainPacket
deriving (Eq, Show)
data VersionNegotiationPacket = VersionNegotiationPacket CID CID [Version]
deriving (Eq, Show)
data RetryPacket
= RetryPacket Version CID CID Token (Either CID (ByteString, ByteString))
deriving (Eq, Show)
data BrokenPacket = BrokenPacket deriving (Eq, Show)
data Header
= Initial Version CID CID Token
| RTT0 Version CID CID
| Handshake Version CID CID
| Short CID
deriving (Eq, Show)
{- FOURMOLU_DISABLE -}
headerMyCID :: Header -> CID
headerMyCID (Initial _ cid _ _) = cid
headerMyCID (RTT0 _ cid _) = cid
headerMyCID (Handshake _ cid _) = cid
headerMyCID (Short cid) = cid
headerPeerCID :: Header -> CID
headerPeerCID (Initial _ _ cid _) = cid
headerPeerCID (RTT0 _ _ cid) = cid
headerPeerCID (Handshake _ _ cid) = cid
headerPeerCID Short{} = CID ""
{- FOURMOLU_ENABLE -}
data PlainPacket = PlainPacket Header Plain deriving (Eq, Show)
data CryptPacket = CryptPacket Header Crypt deriving (Eq, Show)
data Plain = Plain
{ plainFlags :: Flags Raw
, plainPacketNumber :: PacketNumber
, plainFrames :: [Frame]
, plainMarks :: Int
}
deriving (Eq, Show)
defaultPlainMarks :: Int
defaultPlainMarks = 0
setIllegalReservedBits :: Int -> Int
setIllegalReservedBits = (`setBit` 0)
setUnknownFrame :: Int -> Int
setUnknownFrame = (`setBit` 1)
setNoFrames :: Int -> Int
setNoFrames = (`setBit` 2)
setNoPaddings :: Int -> Int
setNoPaddings = (`setBit` 8)
set4bytesPN :: Int -> Int
set4bytesPN = (`setBit` 9)
isIllegalReservedBits :: Int -> Bool
isIllegalReservedBits = (`testBit` 0)
isUnknownFrame :: Int -> Bool
isUnknownFrame = (`testBit` 1)
isNoFrames :: Int -> Bool
isNoFrames = (`testBit` 2)
isNoPaddings :: Int -> Bool
isNoPaddings = (`testBit` 8)
is4bytesPN :: Int -> Bool
is4bytesPN = (`testBit` 9)
data MigrationInfo = MigrationInfo ListenSocket ClientSockAddr CID
deriving (Eq, Show)
data Crypt = Crypt
{ cryptPktNumOffset :: Int
, cryptPacket :: ByteString
, cryptMarks :: Int
, cryptMigraionInfo :: Maybe MigrationInfo
}
deriving (Eq, Show)
isCryptDelayed :: Crypt -> Bool
isCryptDelayed crypt = cryptMarks crypt `testBit` 1
setCryptDelayed :: Crypt -> Crypt
setCryptDelayed crypt = crypt{cryptMarks = cryptMarks crypt `setBit` 1}
data StatelessReset = StatelessReset deriving (Eq, Show)
data ReceivedPacket = ReceivedPacket
{ rpCryptPacket :: CryptPacket
, rpTimeRecevied :: TimeMicrosecond
, rpReceivedBytes :: Int
, rpEncryptionLevel :: EncryptionLevel
}
deriving (Eq, Show)
mkReceivedPacket
:: CryptPacket -> TimeMicrosecond -> Int -> EncryptionLevel -> ReceivedPacket
mkReceivedPacket cpkt tim bytes lvl =
ReceivedPacket
{ rpCryptPacket = cpkt
, rpTimeRecevied = tim
, rpReceivedBytes = bytes
, rpEncryptionLevel = lvl
}
----------------------------------------------------------------
data LongHeaderPacketType
= InitialPacketType
| RTT0PacketType
| HandshakePacketType
| RetryPacketType
deriving (Eq, Show)
data EncryptionLevel
= InitialLevel
| RTT0Level
| HandshakeLevel
| RTT1Level
deriving (Eq, Ord, Ix, Show)
{- FOURMOLU_DISABLE -}
packetEncryptionLevel :: Header -> EncryptionLevel
packetEncryptionLevel Initial{} = InitialLevel
packetEncryptionLevel RTT0{} = RTT0Level
packetEncryptionLevel Handshake{} = HandshakeLevel
packetEncryptionLevel Short{} = RTT1Level
{- FOURMOLU_ENABLE -}
----------------------------------------------------------------
newtype Flags a = Flags Word8 deriving (Eq, Show)
data Protected
data Raw
----------------------------------------------------------------
type EncodedPacketNumber = Word32