http2 1.0.4 → 1.1.0
raw patch · 10 files changed
+180/−101 lines, 10 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Network.HPACK: TooLargeTableSize :: DecodeError
+ Network.HPACK: setLimitForEncoding :: Size -> DynamicTable -> IO ()
Files
- Network/HPACK.hs +3/−2
- Network/HPACK/HeaderBlock/From.hs +25/−22
- Network/HPACK/HeaderBlock/To.hs +44/−23
- Network/HPACK/Table.hs +18/−13
- Network/HPACK/Table/Dynamic.hs +79/−35
- Network/HPACK/Types.hs +1/−0
- Network/HTTP2.hs +2/−2
- Network/HTTP2/RandomSkewHeap.hs +4/−0
- http2.cabal +1/−1
- test-hpack/HPACKDecode.hs +3/−3
Network/HPACK.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE CPP #-} --- | HPACK: encoding and decoding a header list.+-- | HPACK(<https://tools.ietf.org/html/rfc7541>) encoding and decoding a header list. module Network.HPACK ( -- * Encoding and decoding HPACKEncoding@@ -15,6 +15,7 @@ , defaultDynamicTableSize , newDynamicTableForEncoding , newDynamicTableForDecoding+ , setLimitForEncoding -- * Strategy for encoding , CompressionAlgo(..) , EncodeStrategy(..)@@ -39,7 +40,7 @@ import Data.ByteString (ByteString) import Data.ByteString.Builder (Builder) import Network.HPACK.HeaderBlock (toHeaderBlock, fromHeaderBlock, toByteString, fromByteString, toBuilder)-import Network.HPACK.Table (DynamicTable, Size, newDynamicTableForEncoding, newDynamicTableForDecoding)+import Network.HPACK.Table (DynamicTable, Size, newDynamicTableForEncoding, newDynamicTableForDecoding, setLimitForEncoding) import Network.HPACK.Types -- | Default dynamic table size.
Network/HPACK/HeaderBlock/From.hs view
@@ -8,6 +8,8 @@ #if __GLASGOW_HASKELL__ < 709 import Control.Applicative ((<$>)) #endif+import Control.Exception (throwIO)+import Control.Monad (unless) import Network.HPACK.Builder import Network.HPACK.HeaderBlock.HeaderField import Network.HPACK.Table@@ -22,52 +24,53 @@ fromHeaderBlock :: DynamicTable -> HeaderBlock -> IO (DynamicTable, HeaderList)-fromHeaderBlock !hdrtbl rs = decodeLoop rs (hdrtbl,empty)+fromHeaderBlock !dyntbl rs = decodeLoop rs (dyntbl,empty) ---------------------------------------------------------------- decodeLoop :: HeaderBlock -> Ctx -> IO (DynamicTable, HeaderList)-decodeLoop (r:rs) !hdrtbl = decodeStep hdrtbl r >>= decodeLoop rs-decodeLoop [] !hdrtbl = decodeFinal hdrtbl+decodeLoop (r:rs) !dyntbl = decodeStep dyntbl r >>= decodeLoop rs+decodeLoop [] !dyntbl = decodeFinal dyntbl ---------------------------------------------------------------- -- | Decoding step for one 'HeaderField'. Exporting for the -- test purpose. decodeStep :: Step-decodeStep (!hdrtbl,!builder) (ChangeTableSize siz) = do- hdrtbl' <- renewDynamicTable siz hdrtbl- return (hdrtbl',builder)-decodeStep (!hdrtbl,!builder) (Indexed idx) = do- w <- which hdrtbl idx+decodeStep (!dyntbl,!builder) (ChangeTableSize siz) = do+ unless (isSuitableSize siz dyntbl) $ throwIO TooLargeTableSize+ dyntbl' <- renewDynamicTable siz dyntbl+ return (dyntbl',builder)+decodeStep (!dyntbl,!builder) (Indexed idx) = do+ w <- which dyntbl idx case w of (InStaticTable, e) -> do let b = builder << fromEntry e- return (hdrtbl,b)+ return (dyntbl,b) (InDynamicTable, e) -> do let b = builder << fromEntry e- return (hdrtbl,b)-decodeStep (!hdrtbl,!builder) (Literal NotAdd naming v) = do- k <- fromNaming naming hdrtbl+ return (dyntbl,b)+decodeStep (!dyntbl,!builder) (Literal NotAdd naming v) = do+ k <- fromNaming naming dyntbl let b = builder << (k,v)- return (hdrtbl, b)-decodeStep (!hdrtbl,!builder) (Literal Never naming v) = do- k <- fromNaming naming hdrtbl+ return (dyntbl, b)+decodeStep (!dyntbl,!builder) (Literal Never naming v) = do+ k <- fromNaming naming dyntbl let b = builder << (k,v)- return (hdrtbl, b)-decodeStep (!hdrtbl,!builder) (Literal Add naming v) = do- k <- fromNaming naming hdrtbl+ return (dyntbl, b)+decodeStep (!dyntbl,!builder) (Literal Add naming v) = do+ k <- fromNaming naming dyntbl let h = (k,v) e = toEntry (k,v) b = builder << h- hdrtbl' <- insertEntry e hdrtbl- return (hdrtbl',b)+ dyntbl' <- insertEntry e dyntbl+ return (dyntbl',b) decodeFinal :: Ctx -> IO (DynamicTable, HeaderList)-decodeFinal (!hdrtbl, !builder) = return (hdrtbl, run builder)+decodeFinal (!dyntbl, !builder) = return (dyntbl, run builder) ---------------------------------------------------------------- fromNaming :: Naming -> DynamicTable -> IO HeaderName fromNaming (Lit k) _ = return k-fromNaming (Idx idx) hdrtbl = entryHeaderName . snd <$> which hdrtbl idx+fromNaming (Idx idx) dyntbl = entryHeaderName . snd <$> which dyntbl idx
Network/HPACK/HeaderBlock/To.hs view
@@ -1,9 +1,13 @@-{-# LANGUAGE BangPatterns, OverloadedStrings #-}+{-# LANGUAGE BangPatterns, OverloadedStrings, CPP #-} module Network.HPACK.HeaderBlock.To ( toHeaderBlock ) where +#if __GLASGOW_HASKELL__ < 709+import Control.Applicative ((<$>))+#endif+import Control.Arrow (second) import Network.HPACK.Builder import Network.HPACK.HeaderBlock.HeaderField import Network.HPACK.Table@@ -17,39 +21,56 @@ -> DynamicTable -> HeaderList -> IO (DynamicTable, HeaderBlock)-toHeaderBlock Naive !hdrtbl hs = encodeLoop naiveStep hs (hdrtbl,empty)-toHeaderBlock Static !hdrtbl hs = encodeLoop staticStep hs (hdrtbl,empty)-toHeaderBlock Linear !hdrtbl hs = encodeLoop linearStep hs (hdrtbl,empty)+toHeaderBlock algo !dyntbl hs = do+ msiz <- needChangeTableSize dyntbl+ (dyntbl', op) <- case msiz of+ Keep -> do+ return (dyntbl, id)+ Change lim -> do+ tbl <- renewDynamicTable lim dyntbl+ return (tbl, (ChangeTableSize lim :))+ Ignore lim -> do+ resetLimitForEncoding dyntbl+ return (dyntbl, (ChangeTableSize lim :))+ second op <$> toHeaderBlock' algo dyntbl' hs +toHeaderBlock' :: CompressionAlgo+ -> DynamicTable+ -> HeaderList+ -> IO (DynamicTable, HeaderBlock)+toHeaderBlock' Naive !dyntbl hs = encodeLoop naiveStep hs (dyntbl,empty)+toHeaderBlock' Static !dyntbl hs = encodeLoop staticStep hs (dyntbl,empty)+toHeaderBlock' Linear !dyntbl hs = encodeLoop linearStep hs (dyntbl,empty)+ ---------------------------------------------------------------- encodeFinal :: Ctx -> IO (DynamicTable, HeaderBlock)-encodeFinal (!hdrtbl, !builder) = return (hdrtbl, run builder)+encodeFinal (!dyntbl, !builder) = return (dyntbl, run builder) encodeLoop :: Step -> HeaderList -> Ctx -> IO (DynamicTable, HeaderBlock)-encodeLoop step (h:hs) !hdrtbl = step hdrtbl h >>= encodeLoop step hs-encodeLoop _ [] !hdrtbl = encodeFinal hdrtbl+encodeLoop step (h:hs) !dyntbl = step dyntbl h >>= encodeLoop step hs+encodeLoop _ [] !dyntbl = encodeFinal dyntbl ---------------------------------------------------------------- naiveStep :: Step-naiveStep (!hdrtbl,!builder) (k,v) = do+naiveStep (!dyntbl,!builder) (k,v) = do let builder' = builder << Literal NotAdd (Lit k) v- return (hdrtbl, builder')+ return (dyntbl, builder') ---------------------------------------------------------------- staticStep :: Step-staticStep (!hdrtbl,!builder) h@(k,v) = return (hdrtbl, builder')+staticStep (!dyntbl,!builder) h@(k,v) = return (dyntbl, builder') where- b = case lookupTable h hdrtbl of- None -> Literal NotAdd (Lit k) v- KeyOnly InStaticTable i -> Literal NotAdd (Idx i) v+ b = case lookupTable h dyntbl of+ None -> Literal NotAdd (Lit k) v+ KeyOnly InStaticTable i -> Literal NotAdd (Idx i) v KeyOnly InDynamicTable _ -> Literal NotAdd (Lit k) v- KeyValue InStaticTable i -> Literal NotAdd (Idx i) v+ KeyValue InStaticTable i -> Literal NotAdd (Idx i) v KeyValue InDynamicTable _ -> Literal NotAdd (Lit k) v builder' = builder << b @@ -58,32 +79,32 @@ -- by 'Index 0' and uses indexing as much as possible. linearStep :: Step-linearStep cb@(!hdrtbl,!builder) h = smartStep linear cb h+linearStep cb@(!dyntbl,!builder) h = smartStep linear cb h where- linear i = return (hdrtbl,builder << Indexed i)+ linear i = return (dyntbl,builder << Indexed i) ---------------------------------------------------------------- smartStep :: (Index -> IO Ctx) -> Step-smartStep func cb@(!hdrtbl,!builder) h@(k,_) = do- let cache = lookupTable h hdrtbl+smartStep func cb@(!dyntbl,!builder) h@(k,_) = do+ let cache = lookupTable h dyntbl case cache of None -> check cb h (Lit k) KeyOnly InStaticTable i -> check cb h (Idx i) KeyOnly InDynamicTable i -> check cb h (Idx i)- KeyValue InStaticTable i -> return (hdrtbl, builder << Indexed i)+ KeyValue InStaticTable i -> return (dyntbl, builder << Indexed i) KeyValue InDynamicTable i -> func i check :: Ctx -> Header -> Naming -> IO Ctx-check (hdrtbl,builder) h@(k,v) x+check (dyntbl,builder) h@(k,v) x | k `elem` headersNotToIndex = do let builder' = builder << Literal NotAdd x v- return (hdrtbl, builder')+ return (dyntbl, builder') | otherwise = do let e = toEntry h- hdrtbl' <- insertEntry e hdrtbl+ dyntbl' <- insertEntry e dyntbl let builder' = builder << Literal Add x v- return (hdrtbl', builder')+ return (dyntbl', builder') headersNotToIndex :: [HeaderName] headersNotToIndex = [
Network/HPACK/Table.hs view
@@ -8,6 +8,11 @@ , renewDynamicTable , printDynamicTable , isDynamicTableEmpty+ , isSuitableSize+ , TableSizeAction(..)+ , needChangeTableSize+ , setLimitForEncoding+ , resetLimitForEncoding -- * Insertion , insertEntry -- * Header to index@@ -45,21 +50,21 @@ -- | Resolving an index from a header. -- Static table is prefer to dynamic table. lookupTable :: Header -> DynamicTable -> HeaderCache-lookupTable h hdrtbl = case reverseIndex hdrtbl of+lookupTable h dyntbl = case reverseIndex dyntbl of Nothing -> None Just rev -> case DHM.search h rev of DHM.N -> case mstatic of DHM.N -> None- DHM.K sidx -> KeyOnly InStaticTable (fromSIndexToIndex hdrtbl sidx)- DHM.KV sidx -> KeyValue InStaticTable (fromSIndexToIndex hdrtbl sidx)+ DHM.K sidx -> KeyOnly InStaticTable (fromSIndexToIndex dyntbl sidx)+ DHM.KV sidx -> KeyValue InStaticTable (fromSIndexToIndex dyntbl sidx) DHM.K hidx -> case mstatic of- DHM.N -> KeyOnly InDynamicTable (fromHIndexToIndex hdrtbl hidx)- DHM.K sidx -> KeyOnly InStaticTable (fromSIndexToIndex hdrtbl sidx)- DHM.KV sidx -> KeyValue InStaticTable (fromSIndexToIndex hdrtbl sidx)+ DHM.N -> KeyOnly InDynamicTable (fromHIndexToIndex dyntbl hidx)+ DHM.K sidx -> KeyOnly InStaticTable (fromSIndexToIndex dyntbl sidx)+ DHM.KV sidx -> KeyValue InStaticTable (fromSIndexToIndex dyntbl sidx) DHM.KV hidx -> case mstatic of- DHM.N -> KeyValue InDynamicTable (fromHIndexToIndex hdrtbl hidx)- DHM.K _ -> KeyValue InDynamicTable (fromHIndexToIndex hdrtbl hidx)- DHM.KV sidx -> KeyValue InStaticTable (fromSIndexToIndex hdrtbl sidx)+ DHM.N -> KeyValue InDynamicTable (fromHIndexToIndex dyntbl hidx)+ DHM.K _ -> KeyValue InDynamicTable (fromHIndexToIndex dyntbl hidx)+ DHM.KV sidx -> KeyValue InStaticTable (fromSIndexToIndex dyntbl sidx) where mstatic = DHM.search h staticHashPSQ @@ -70,10 +75,10 @@ -- | Which table does 'Index' belong to? which :: DynamicTable -> Index -> IO (WhichTable, Entry)-which hdrtbl idx- | idx `isIn` hdrtbl = (InDynamicTable,) <$> toHeaderEntry hdrtbl hidx+which dyntbl idx+ | idx `isIn` dyntbl = (InDynamicTable,) <$> toHeaderEntry dyntbl hidx | isSIndexValid sidx = return (InStaticTable, toStaticEntry sidx) | otherwise = throwIO $ IndexOverrun idx where- hidx = fromIndexToHIndex hdrtbl idx- sidx = fromIndexToSIndex hdrtbl idx+ hidx = fromIndexToHIndex dyntbl idx+ sidx = fromIndexToSIndex dyntbl idx
Network/HPACK/Table/Dynamic.hs view
@@ -7,6 +7,11 @@ , renewDynamicTable , printDynamicTable , isDynamicTableEmpty+ , isSuitableSize+ , TableSizeAction(..)+ , needChangeTableSize+ , setLimitForEncoding+ , resetLimitForEncoding , insertEntry , toHeaderEntry , fromHIndexToIndex@@ -15,12 +20,13 @@ , fromIndexToSIndex ) where +import Control.Monad (forM) import Data.Array.IO (IOArray, newArray, readArray, writeArray) import qualified Data.ByteString.Char8 as BS-import Network.HPACK.Table.Entry+import Data.IORef import qualified Network.HPACK.Table.DoubleHashMap as DHM+import Network.HPACK.Table.Entry import Network.HPACK.Table.Static-import Control.Monad (forM) ---------------------------------------------------------------- @@ -58,6 +64,13 @@ , headerTableSize :: !Size -- | The max dynamic table size (defined in HPACK) , maxDynamicTableSize :: !Size+ -- | The value informed by SETTINGS_HEADER_TABLE_SIZE.+ -- If 'Nothing', dynamic table size update is not necessary.+ -- Otherwise, dynamic table size update is sent+ -- and this value should be set to 'Nothing'.+ , limitForEncoding :: IORef (Maybe Size)+ -- | The limit size of a dynamic table for decoding+ , limitForDecoding :: !Size -- | Header to the index in Dynamic Table for encoder. -- Static Table is not included. -- Nothing for decoder.@@ -95,8 +108,35 @@ ---------------------------------------------------------------- isDynamicTableEmpty :: DynamicTable -> Bool-isDynamicTableEmpty hdrtbl = numOfEntries hdrtbl == 0+isDynamicTableEmpty dyntbl = numOfEntries dyntbl == 0 +isSuitableSize :: Size -> DynamicTable -> Bool+isSuitableSize siz tbl = siz <= limitForDecoding tbl++data TableSizeAction = Keep | Change Size | Ignore Size++needChangeTableSize :: DynamicTable -> IO TableSizeAction+needChangeTableSize tbl = do+ mlim <- getLimitForEncoding tbl+ return $ case mlim of+ Nothing -> Keep+ Just lim+ | lim < maxsiz -> Change lim+ | otherwise -> Ignore maxsiz+ where+ maxsiz = maxDynamicTableSize tbl++getLimitForEncoding :: DynamicTable -> IO (Maybe Size)+getLimitForEncoding dyntbl = readIORef $ limitForEncoding dyntbl++-- | When SETTINGS_HEADER_TABLE_SIZE is received from a peer,+-- its value should be set by this function.+setLimitForEncoding :: Size -> DynamicTable -> IO ()+setLimitForEncoding siz dyntbl = writeIORef (limitForEncoding dyntbl) $ Just siz++resetLimitForEncoding :: DynamicTable -> IO ()+resetLimitForEncoding dyntbl = writeIORef (limitForEncoding dyntbl) Nothing+ ---------------------------------------------------------------- -- Physical array index for Dynamic Table.@@ -124,15 +164,16 @@ -- | Creating 'DynamicTable'. newDynamicTableForEncoding :: Size -> IO DynamicTable-newDynamicTableForEncoding maxsiz = newDynamicTable maxsiz (Just DHM.empty)+newDynamicTableForEncoding maxsiz = newDynamicTable maxsiz maxsiz (Just DHM.empty) -- | Creating 'DynamicTable'. newDynamicTableForDecoding :: Size -> IO DynamicTable-newDynamicTableForDecoding maxsiz = newDynamicTable maxsiz Nothing+newDynamicTableForDecoding maxsiz = newDynamicTable maxsiz maxsiz Nothing -newDynamicTable :: Size -> Maybe (DHM.DoubleHashMap HIndex) -> IO DynamicTable-newDynamicTable maxsiz mhp = do+newDynamicTable :: Size -> Size -> Maybe (DHM.DoubleHashMap HIndex) -> IO DynamicTable+newDynamicTable maxsiz dlim mhp = do tbl <- newArray (0,end) dummyEntry+ lim <- newIORef Nothing return DynamicTable { maxNumOfEntries = maxN , offset = end@@ -140,6 +181,8 @@ , circularTable = tbl , headerTableSize = 0 , maxDynamicTableSize = maxsiz+ , limitForEncoding = lim+ , limitForDecoding = dlim , reverseIndex = mhp } where@@ -148,16 +191,17 @@ -- | Renewing 'DynamicTable' with necessary entries copied. renewDynamicTable :: Size -> DynamicTable -> IO DynamicTable-renewDynamicTable maxsiz oldhdrtbl | shouldRenew oldhdrtbl maxsiz =- newDynamicTable maxsiz mhp >>= copyTable oldhdrtbl+renewDynamicTable maxsiz olddyntbl | shouldRenew olddyntbl maxsiz =+ newDynamicTable maxsiz dlim mhp >>= copyTable olddyntbl where- mhp = case reverseIndex oldhdrtbl of+ dlim = limitForDecoding olddyntbl+ mhp = case reverseIndex olddyntbl of Nothing -> Nothing _ -> Just DHM.empty-renewDynamicTable _ oldhdrtbl = return oldhdrtbl+renewDynamicTable _ olddyntbl = return olddyntbl copyTable :: DynamicTable -> DynamicTable -> IO DynamicTable-copyTable oldhdrtbl newhdrtbl = getEntries oldhdrtbl >>= copyEntries newhdrtbl+copyTable olddyntbl newdyntbl = getEntries olddyntbl >>= copyEntries newdyntbl getEntries :: DynamicTable -> IO [Entry] getEntries DynamicTable{..} = forM [1 .. numOfEntries] readTable@@ -165,12 +209,12 @@ readTable i = readArray circularTable $ adj maxNumOfEntries (offset + i) copyEntries :: DynamicTable -> [Entry] -> IO DynamicTable-copyEntries hdrtbl [] = return hdrtbl-copyEntries hdrtbl@DynamicTable{..} (e:es)+copyEntries dyntbl [] = return dyntbl+copyEntries dyntbl@DynamicTable{..} (e:es) | headerTableSize + entrySize e <= maxDynamicTableSize = do- hdrtbl' <- insertEnd e hdrtbl- copyEntries hdrtbl' es- | otherwise = return hdrtbl+ dyntbl' <- insertEnd e dyntbl+ copyEntries dyntbl' es+ | otherwise = return dyntbl -- | Is the size of 'DynamicTable' really changed? shouldRenew :: DynamicTable -> Size -> Bool@@ -183,17 +227,17 @@ -- and a set of dropped OLD 'Index' -- are returned. insertEntry :: Entry -> DynamicTable -> IO DynamicTable-insertEntry e hdrtbl = do- (hdrtbl', hs) <- insertFront e hdrtbl >>= adjustTableSize- let hdrtbl'' = case reverseIndex hdrtbl' of- Nothing -> hdrtbl'- Just rev -> hdrtbl' { reverseIndex = Just (DHM.deleteList hs rev) }- return hdrtbl''+insertEntry e dyntbl = do+ (dyntbl', hs) <- insertFront e dyntbl >>= adjustTableSize+ let dyntbl'' = case reverseIndex dyntbl' of+ Nothing -> dyntbl'+ Just rev -> dyntbl' { reverseIndex = Just (DHM.deleteList hs rev) }+ return dyntbl'' insertFront :: Entry -> DynamicTable -> IO DynamicTable-insertFront e hdrtbl@DynamicTable{..} = do+insertFront e dyntbl@DynamicTable{..} = do writeArray circularTable i e- return $ hdrtbl {+ return $ dyntbl { offset = offset' , numOfEntries = numOfEntries + 1 , headerTableSize = headerTableSize'@@ -208,21 +252,21 @@ Just rev -> Just $ DHM.insert (entryHeader e) (HIndex i) rev adjustTableSize :: DynamicTable -> IO (DynamicTable, [Header])-adjustTableSize hdrtbl = adjust hdrtbl []+adjustTableSize dyntbl = adjust dyntbl [] adjust :: DynamicTable -> [Header] -> IO (DynamicTable, [Header])-adjust hdrtbl@DynamicTable{..} hs- | headerTableSize <= maxDynamicTableSize = return (hdrtbl, hs)+adjust dyntbl@DynamicTable{..} hs+ | headerTableSize <= maxDynamicTableSize = return (dyntbl, hs) | otherwise = do- (hdrtbl', h) <- removeEnd hdrtbl- adjust hdrtbl' (h:hs)+ (dyntbl', h) <- removeEnd dyntbl+ adjust dyntbl' (h:hs) ---------------------------------------------------------------- insertEnd :: Entry -> DynamicTable -> IO DynamicTable-insertEnd e hdrtbl@DynamicTable{..} = do+insertEnd e dyntbl@DynamicTable{..} = do writeArray circularTable i e- return $ hdrtbl {+ return $ dyntbl { numOfEntries = numOfEntries + 1 , headerTableSize = headerTableSize' , reverseIndex = reverseIndex'@@ -237,17 +281,17 @@ ---------------------------------------------------------------- removeEnd :: DynamicTable -> IO (DynamicTable,Header)-removeEnd hdrtbl@DynamicTable{..} = do+removeEnd dyntbl@DynamicTable{..} = do let i = adj maxNumOfEntries (offset + numOfEntries) e <- readArray circularTable i writeArray circularTable i dummyEntry -- let the entry GCed let tsize = headerTableSize - entrySize e h = entryHeader e- hdrtbl' = hdrtbl {+ dyntbl' = dyntbl { numOfEntries = numOfEntries - 1 , headerTableSize = tsize }- return (hdrtbl', h)+ return (dyntbl', h) ----------------------------------------------------------------
Network/HPACK/Types.hs view
@@ -70,6 +70,7 @@ | TooLongEos -- ^ Eos of huffman string is more than 7 bits | EmptyEncodedString -- ^ Encoded string has no length | EmptyBlock -- ^ Header block is empty+ | TooLargeTableSize -- ^ A peer tried to change the dynamic table size over the limit deriving (Eq,Show,Typeable) instance Exception DecodeError
Network/HTTP2.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} --- | Framing in HTTP/2.+-- | Framing in HTTP\/2(<https://tools.ietf.org/html/rfc7540>). module Network.HTTP2 ( -- * Frame Frame(..)@@ -91,7 +91,7 @@ import Network.HTTP2.Encode import Network.HTTP2.Types --- | The preface of HTTP/2.+-- | The preface of HTTP\/2. -- -- >>> connectionPreface -- "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
Network/HTTP2/RandomSkewHeap.hs view
@@ -71,10 +71,13 @@ gen = unsafePerformIO createSystemRandom {-# NOINLINE gen #-} +{-+main :: IO () main = do let q = insert "c" 1 $ insert "b" 101 $ insert "a" 201 empty loop 1000 q where+ loop :: Int -> Heap String -> IO () loop 0 _ = return () loop n q = do case uncons q of@@ -82,3 +85,4 @@ Just (x, w, q') -> do putStrLn x loop (n-1) (insert x w q')+-}
http2.cabal view
@@ -1,5 +1,5 @@ Name: http2-Version: 1.0.4+Version: 1.1.0 Author: Kazu Yamamoto <kazu@iij.ad.jp> Maintainer: Kazu Yamamoto <kazu@iij.ad.jp> License: BSD3
test-hpack/HPACKDecode.hs view
@@ -30,9 +30,9 @@ run :: Bool -> Test -> IO Result run _ (Test _ []) = return $ Pass-run d (Test _ ccs@(c:_)) = do- let siz = maybe 4096 id $ size c- dhdrtbl <- newDynamicTableForDecoding siz+run d (Test _ ccs) = do+ -- 'size c' must not be used. Initial value is 4,096!+ dhdrtbl <- newDynamicTableForDecoding 4096 let conf = Conf { debug = d } testLoop conf ccs dhdrtbl