{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}

module Network.HTTP2.Server.Sender (frameSender) where

import Control.Concurrent.STM
import qualified Control.Exception as E
import qualified Data.ByteString as BS
import Data.ByteString.Builder (Builder)
import qualified Data.ByteString.Builder.Extra as B
import Data.IORef
import Foreign.Ptr (plusPtr)
import Network.ByteOrder

import Imports
import Network.HPACK (setLimitForEncoding, toHeaderTable)
import Network.HTTP2
import Network.HTTP2.Priority (isEmptySTM, dequeueSTM, Precedence)
import Network.HTTP2.Server.API
import Network.HTTP2.Server.EncodeFrame
import Network.HTTP2.Server.HPACK
import Network.HTTP2.Server.Manager hiding (start)
import Network.HTTP2.Server.Types
import Network.HTTP2.Server.Queue
import Network.HTTP2.Server.Context
import Network.HTTP2.Server.Stream

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

data Leftover = LZero
              | LOne B.BufferWriter
              | LTwo ByteString B.BufferWriter

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

{-# INLINE getStreamWindowSize #-}
getStreamWindowSize :: Stream -> IO WindowSize
getStreamWindowSize :: Stream -> IO WindowSize
getStreamWindowSize Stream{TVar WindowSize
streamWindow :: Stream -> TVar WindowSize
streamWindow :: TVar WindowSize
streamWindow} = TVar WindowSize -> IO WindowSize
forall a. TVar a -> IO a
readTVarIO TVar WindowSize
streamWindow

{-# INLINE waitStreamWindowSize #-}
waitStreamWindowSize :: Stream -> IO ()
waitStreamWindowSize :: Stream -> IO ()
waitStreamWindowSize Stream{TVar WindowSize
streamWindow :: TVar WindowSize
streamWindow :: Stream -> TVar WindowSize
streamWindow} = STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
    WindowSize
w <- TVar WindowSize -> STM WindowSize
forall a. TVar a -> STM a
readTVar TVar WindowSize
streamWindow
    Bool -> STM ()
check (WindowSize
w WindowSize -> WindowSize -> Bool
forall a. Ord a => a -> a -> Bool
> 0)

{-# INLINE waitStreaming #-}
waitStreaming :: TBQueue a -> IO ()
waitStreaming :: TBQueue a -> IO ()
waitStreaming tbq :: TBQueue a
tbq = STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
    Bool
isEmpty <- TBQueue a -> STM Bool
forall a. TBQueue a -> STM Bool
isEmptyTBQueue TBQueue a
tbq
    Bool -> STM ()
check (Bool -> Bool
not Bool
isEmpty)

data Switch = C Control
            | O (StreamId,Precedence,Output)
            | Flush

frameSender :: Context -> Config -> Manager -> IO ()
frameSender :: Context -> Config -> Manager -> IO ()
frameSender ctx :: Context
ctx@Context{PriorityTree Output
outputQ :: Context -> PriorityTree Output
outputQ :: PriorityTree Output
outputQ,TQueue Control
controlQ :: Context -> TQueue Control
controlQ :: TQueue Control
controlQ,TVar WindowSize
connectionWindow :: Context -> TVar WindowSize
connectionWindow :: TVar WindowSize
connectionWindow,DynamicTable
encodeDynamicTable :: Context -> DynamicTable
encodeDynamicTable :: DynamicTable
encodeDynamicTable}
            conf :: Config
conf@Config{..}
            mgr :: Manager
mgr = WindowSize -> IO ()
loop 0 IO () -> (SomeException -> IO ()) -> IO ()
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
`E.catch` SomeException -> IO ()
ignore
  where
    dequeue :: a -> STM Switch
dequeue off :: a
off = do
        Bool
isEmpty <- TQueue Control -> STM Bool
forall a. TQueue a -> STM Bool
isEmptyTQueue TQueue Control
controlQ
        if Bool
isEmpty then do
            WindowSize
w <- TVar WindowSize -> STM WindowSize
forall a. TVar a -> STM a
readTVar TVar WindowSize
connectionWindow
            Bool -> STM ()
check (WindowSize
w WindowSize -> WindowSize -> Bool
forall a. Ord a => a -> a -> Bool
> 0)
            Bool
emp <- PriorityTree Output -> STM Bool
forall a. PriorityTree a -> STM Bool
isEmptySTM PriorityTree Output
outputQ
            if Bool
emp then
                if a
off a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= 0 then Switch -> STM Switch
forall (m :: * -> *) a. Monad m => a -> m a
return Switch
Flush else STM Switch
forall a. STM a
retry
              else
                (WindowSize, Precedence, Output) -> Switch
O ((WindowSize, Precedence, Output) -> Switch)
-> STM (WindowSize, Precedence, Output) -> STM Switch
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> PriorityTree Output -> STM (WindowSize, Precedence, Output)
forall a. PriorityTree a -> STM (WindowSize, Precedence, a)
dequeueSTM PriorityTree Output
outputQ
          else
            Control -> Switch
C (Control -> Switch) -> STM Control -> STM Switch
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TQueue Control -> STM Control
forall a. TQueue a -> STM a
readTQueue TQueue Control
controlQ

    hardLimit :: WindowSize
hardLimit = WindowSize
confBufferSize WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
- 512

    loop :: WindowSize -> IO ()
loop off :: WindowSize
off = do
        Switch
x <- STM Switch -> IO Switch
forall a. STM a -> IO a
atomically (STM Switch -> IO Switch) -> STM Switch -> IO Switch
forall a b. (a -> b) -> a -> b
$ WindowSize -> STM Switch
forall a. (Eq a, Num a) => a -> STM Switch
dequeue WindowSize
off
        case Switch
x of
            C ctl :: Control
ctl -> do
                Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (WindowSize
off WindowSize -> WindowSize -> Bool
forall a. Eq a => a -> a -> Bool
/= 0) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ WindowSize -> IO ()
flushN WindowSize
off
                WindowSize
off' <- Control -> WindowSize -> IO WindowSize
control Control
ctl WindowSize
off
                Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (WindowSize
off' WindowSize -> WindowSize -> Bool
forall a. Ord a => a -> a -> Bool
>= 0) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ WindowSize -> IO ()
loop WindowSize
off'
            O (_,pre :: Precedence
pre,out :: Output
out) -> do
                let strm :: Stream
strm = Output -> Stream
outputStream Output
out
                IORef Precedence -> Precedence -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef (Stream -> IORef Precedence
streamPrecedence Stream
strm) Precedence
pre
                WindowSize
off' <- Output -> WindowSize -> IO WindowSize
outputOrEnqueueAgain Output
out WindowSize
off
                case WindowSize
off' of
                    0                    -> WindowSize -> IO ()
loop 0
                    _ | WindowSize
off' WindowSize -> WindowSize -> Bool
forall a. Ord a => a -> a -> Bool
> WindowSize
hardLimit -> WindowSize -> IO ()
flushN WindowSize
off' IO () -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> WindowSize -> IO ()
loop 0
                      | Bool
otherwise        -> WindowSize -> IO ()
loop WindowSize
off'
            Flush -> WindowSize -> IO ()
flushN WindowSize
off IO () -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> WindowSize -> IO ()
loop 0

    control :: Control -> WindowSize -> IO WindowSize
control CFinish         _ = WindowSize -> IO WindowSize
forall (m :: * -> *) a. Monad m => a -> m a
return (-1)
    control (CGoaway frame :: ByteString
frame) _ = ByteString -> IO ()
confSendAll ByteString
frame IO () -> IO WindowSize -> IO WindowSize
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> WindowSize -> IO WindowSize
forall (m :: * -> *) a. Monad m => a -> m a
return (-1)
    control (CFrame frame :: ByteString
frame)  _ = ByteString -> IO ()
confSendAll ByteString
frame IO () -> IO WindowSize -> IO WindowSize
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> WindowSize -> IO WindowSize
forall (m :: * -> *) a. Monad m => a -> m a
return 0
    control (CSettings frame :: ByteString
frame alist :: SettingsList
alist) _ = do
        ByteString -> IO ()
confSendAll ByteString
frame
        SettingsList -> IO ()
setLimit SettingsList
alist
        WindowSize -> IO WindowSize
forall (m :: * -> *) a. Monad m => a -> m a
return 0
    control (CSettings0 frame1 :: ByteString
frame1 frame2 :: ByteString
frame2 alist :: SettingsList
alist) off :: WindowSize
off = do -- off == 0, just in case
        let !buf :: Ptr b
buf = Buffer
confWriteBuffer Buffer -> WindowSize -> Ptr b
forall a b. Ptr a -> WindowSize -> Ptr b
`plusPtr` WindowSize
off
            !off' :: WindowSize
off' = WindowSize
off WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+ ByteString -> WindowSize
BS.length ByteString
frame1 WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+ ByteString -> WindowSize
BS.length ByteString
frame2
        Buffer
buf' <- Buffer -> ByteString -> IO Buffer
copy Buffer
forall b. Ptr b
buf ByteString
frame1
        IO Buffer -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO Buffer -> IO ()) -> IO Buffer -> IO ()
forall a b. (a -> b) -> a -> b
$ Buffer -> ByteString -> IO Buffer
copy Buffer
buf' ByteString
frame2
        SettingsList -> IO ()
setLimit SettingsList
alist
        WindowSize -> IO WindowSize
forall (m :: * -> *) a. Monad m => a -> m a
return WindowSize
off'

    {-# INLINE setLimit #-}
    setLimit :: SettingsList -> IO ()
setLimit alist :: SettingsList
alist = case SettingsKeyId -> SettingsList -> Maybe WindowSize
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup SettingsKeyId
SettingsHeaderTableSize SettingsList
alist of
        Nothing  -> () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
        Just siz :: WindowSize
siz -> WindowSize -> DynamicTable -> IO ()
setLimitForEncoding WindowSize
siz DynamicTable
encodeDynamicTable

    output :: Output -> WindowSize -> WindowSize -> IO WindowSize
output out :: Output
out@(Output strm :: Stream
strm (Response _ _ _ _) (ONext curr :: DynaNext
curr tlrmkr :: TrailersMaker
tlrmkr) _ sentinel :: IO ()
sentinel) off0 :: WindowSize
off0 lim :: WindowSize
lim = do
        -- Data frame payload
        let !buf :: Ptr b
buf = Buffer
confWriteBuffer Buffer -> WindowSize -> Ptr b
forall a b. Ptr a -> WindowSize -> Ptr b
`plusPtr` WindowSize
off0
            !siz :: WindowSize
siz = WindowSize
confBufferSize WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
- WindowSize
off0
            !payloadOff :: WindowSize
payloadOff = WindowSize
off0 WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+ WindowSize
frameHeaderLength
        Next datPayloadLen :: WindowSize
datPayloadLen mnext :: Maybe DynaNext
mnext <- DynaNext
curr Buffer
forall b. Ptr b
buf WindowSize
siz WindowSize
lim
        NextTrailersMaker !TrailersMaker
tlrmkr' <- TrailersMaker -> WindowSize -> WindowSize -> IO NextTrailersMaker
forall a.
(Maybe ByteString -> IO a) -> WindowSize -> WindowSize -> IO a
runTrailersMaker TrailersMaker
tlrmkr WindowSize
payloadOff WindowSize
datPayloadLen
        Stream
-> WindowSize
-> WindowSize
-> Maybe DynaNext
-> TrailersMaker
-> IO ()
-> Output
-> IO WindowSize
forall a.
Stream
-> WindowSize
-> WindowSize
-> Maybe DynaNext
-> TrailersMaker
-> IO a
-> Output
-> IO WindowSize
fillDataHeaderEnqueueNext Stream
strm WindowSize
off0 WindowSize
datPayloadLen Maybe DynaNext
mnext TrailersMaker
tlrmkr' IO ()
sentinel Output
out

    output out :: Output
out@(Output strm :: Stream
strm (Response st :: Status
st hdr :: ResponseHeaders
hdr body :: ResponseBody
body tlrmkr :: TrailersMaker
tlrmkr) ORspn mtbq :: Maybe (TBQueue RspStreaming)
mtbq sentinel :: IO ()
sentinel) off0 :: WindowSize
off0 lim :: WindowSize
lim = do
        -- Header frame and Continuation frame
        let !sid :: WindowSize
sid = Stream -> WindowSize
streamNumber Stream
strm
            !endOfStream :: Bool
endOfStream = case ResponseBody
body of
                RspNoBody -> Bool
True
                _         -> Bool
False
        (ths :: TokenHeaderList
ths,_) <- ResponseHeaders -> IO (TokenHeaderList, ValueTable)
toHeaderTable (ResponseHeaders -> IO (TokenHeaderList, ValueTable))
-> ResponseHeaders -> IO (TokenHeaderList, ValueTable)
forall a b. (a -> b) -> a -> b
$ Status -> ResponseHeaders -> ResponseHeaders
fixHeaders Status
st ResponseHeaders
hdr
        WindowSize
kvlen <- WindowSize
-> TokenHeaderList -> Bool -> WindowSize -> IO WindowSize
headerContinue WindowSize
sid TokenHeaderList
ths Bool
endOfStream WindowSize
off0
        WindowSize
off <- WindowSize -> IO WindowSize
sendHeadersIfNecessary (WindowSize -> IO WindowSize) -> WindowSize -> IO WindowSize
forall a b. (a -> b) -> a -> b
$ WindowSize
off0 WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+ WindowSize
frameHeaderLength WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+ WindowSize
kvlen
        case ResponseBody
body of
            RspNoBody -> do
                Context -> Stream -> ClosedCode -> IO ()
halfClosedLocal Context
ctx Stream
strm ClosedCode
Finished
                WindowSize -> IO WindowSize
forall (m :: * -> *) a. Monad m => a -> m a
return WindowSize
off
            RspFile (FileSpec path :: FilePath
path fileoff :: FileOffset
fileoff bytecount :: FileOffset
bytecount) -> do
                -- Data frame payload
                let payloadOff :: WindowSize
payloadOff = WindowSize
off WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+ WindowSize
frameHeaderLength
                Next datPayloadLen :: WindowSize
datPayloadLen mnext :: Maybe DynaNext
mnext <-
                    Config
-> WindowSize
-> WindowSize
-> FilePath
-> FileOffset
-> FileOffset
-> Manager
-> PositionReadMaker
-> IO Next
fillFileBodyGetNext Config
conf WindowSize
payloadOff WindowSize
lim FilePath
path FileOffset
fileoff FileOffset
bytecount Manager
mgr PositionReadMaker
confPositionReadMaker
                NextTrailersMaker !TrailersMaker
tlrmkr' <- TrailersMaker -> WindowSize -> WindowSize -> IO NextTrailersMaker
forall a.
(Maybe ByteString -> IO a) -> WindowSize -> WindowSize -> IO a
runTrailersMaker TrailersMaker
tlrmkr WindowSize
payloadOff WindowSize
datPayloadLen
                Stream
-> WindowSize
-> WindowSize
-> Maybe DynaNext
-> TrailersMaker
-> IO ()
-> Output
-> IO WindowSize
forall a.
Stream
-> WindowSize
-> WindowSize
-> Maybe DynaNext
-> TrailersMaker
-> IO a
-> Output
-> IO WindowSize
fillDataHeaderEnqueueNext Stream
strm WindowSize
off WindowSize
datPayloadLen Maybe DynaNext
mnext TrailersMaker
tlrmkr' IO ()
sentinel Output
out
            RspBuilder builder :: Builder
builder -> do
                -- Data frame payload
                let payloadOff :: WindowSize
payloadOff = WindowSize
off WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+ WindowSize
frameHeaderLength
                Next datPayloadLen :: WindowSize
datPayloadLen mnext :: Maybe DynaNext
mnext <-
                    Config -> WindowSize -> WindowSize -> Builder -> IO Next
fillBuilderBodyGetNext Config
conf WindowSize
payloadOff WindowSize
lim Builder
builder
                NextTrailersMaker !TrailersMaker
tlrmkr' <- TrailersMaker -> WindowSize -> WindowSize -> IO NextTrailersMaker
forall a.
(Maybe ByteString -> IO a) -> WindowSize -> WindowSize -> IO a
runTrailersMaker TrailersMaker
tlrmkr WindowSize
payloadOff WindowSize
datPayloadLen
                Stream
-> WindowSize
-> WindowSize
-> Maybe DynaNext
-> TrailersMaker
-> IO ()
-> Output
-> IO WindowSize
forall a.
Stream
-> WindowSize
-> WindowSize
-> Maybe DynaNext
-> TrailersMaker
-> IO a
-> Output
-> IO WindowSize
fillDataHeaderEnqueueNext Stream
strm WindowSize
off WindowSize
datPayloadLen Maybe DynaNext
mnext TrailersMaker
tlrmkr' IO ()
sentinel Output
out
            RspStreaming _ -> do
                let payloadOff :: WindowSize
payloadOff = WindowSize
off WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+ WindowSize
frameHeaderLength
                Next datPayloadLen :: WindowSize
datPayloadLen mnext :: Maybe DynaNext
mnext <-
                    Config
-> WindowSize
-> WindowSize
-> TBQueue RspStreaming
-> Stream
-> IO Next
fillStreamBodyGetNext Config
conf WindowSize
payloadOff WindowSize
lim (Maybe (TBQueue RspStreaming) -> TBQueue RspStreaming
forall a. HasCallStack => Maybe a -> a
fromJust Maybe (TBQueue RspStreaming)
mtbq) Stream
strm
                NextTrailersMaker !TrailersMaker
tlrmkr' <- TrailersMaker -> WindowSize -> WindowSize -> IO NextTrailersMaker
forall a.
(Maybe ByteString -> IO a) -> WindowSize -> WindowSize -> IO a
runTrailersMaker TrailersMaker
tlrmkr WindowSize
payloadOff WindowSize
datPayloadLen
                Stream
-> WindowSize
-> WindowSize
-> Maybe DynaNext
-> TrailersMaker
-> IO ()
-> Output
-> IO WindowSize
forall a.
Stream
-> WindowSize
-> WindowSize
-> Maybe DynaNext
-> TrailersMaker
-> IO a
-> Output
-> IO WindowSize
fillDataHeaderEnqueueNext Stream
strm WindowSize
off WindowSize
datPayloadLen Maybe DynaNext
mnext TrailersMaker
tlrmkr' IO ()
sentinel Output
out

    output out :: Output
out@(Output strm :: Stream
strm _ (OPush ths :: TokenHeaderList
ths pid :: WindowSize
pid) _ _) off0 :: WindowSize
off0 lim :: WindowSize
lim = do
        -- Creating a push promise header
        -- Frame id should be associated stream id from the client.
        let !sid :: WindowSize
sid = Stream -> WindowSize
streamNumber Stream
strm
        WindowSize
len <- WindowSize
-> WindowSize -> TokenHeaderList -> WindowSize -> IO WindowSize
forall a.
Integral a =>
WindowSize -> a -> TokenHeaderList -> WindowSize -> IO WindowSize
pushPromise WindowSize
pid WindowSize
sid TokenHeaderList
ths WindowSize
off0
        WindowSize
off <- WindowSize -> IO WindowSize
sendHeadersIfNecessary (WindowSize -> IO WindowSize) -> WindowSize -> IO WindowSize
forall a b. (a -> b) -> a -> b
$ WindowSize
off0 WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+ WindowSize
frameHeaderLength WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+ WindowSize
len
        Output -> WindowSize -> WindowSize -> IO WindowSize
output Output
out{outputType :: OutputType
outputType=OutputType
ORspn} WindowSize
off WindowSize
lim

    output _ _ _ = IO WindowSize
forall a. HasCallStack => a
undefined -- never reach

    outputOrEnqueueAgain :: Output -> Int -> IO Int
    outputOrEnqueueAgain :: Output -> WindowSize -> IO WindowSize
outputOrEnqueueAgain out :: Output
out@(Output strm :: Stream
strm _ otyp :: OutputType
otyp _ _) off :: WindowSize
off = (SomeException -> IO WindowSize) -> IO WindowSize -> IO WindowSize
forall e a. Exception e => (e -> IO a) -> IO a -> IO a
E.handle SomeException -> IO WindowSize
resetStream (IO WindowSize -> IO WindowSize) -> IO WindowSize -> IO WindowSize
forall a b. (a -> b) -> a -> b
$ do
        StreamState
state <- Stream -> IO StreamState
readStreamState Stream
strm
        if StreamState -> Bool
isHalfClosedLocal StreamState
state then
            WindowSize -> IO WindowSize
forall (m :: * -> *) a. Monad m => a -> m a
return WindowSize
off
          else case OutputType
otyp of
                 OWait wait :: IO ()
wait -> do
                     -- Checking if all push are done.
                     IO () -> PriorityTree Output -> Output -> Manager -> IO ()
forkAndEnqueueWhenReady IO ()
wait PriorityTree Output
outputQ Output
out{outputType :: OutputType
outputType=OutputType
ORspn} Manager
mgr
                     WindowSize -> IO WindowSize
forall (m :: * -> *) a. Monad m => a -> m a
return WindowSize
off
                 _ -> case Maybe (TBQueue RspStreaming)
mtbq of
                        Just tbq :: TBQueue RspStreaming
tbq -> TBQueue RspStreaming -> IO WindowSize
forall a. TBQueue a -> IO WindowSize
checkStreaming TBQueue RspStreaming
tbq
                        _        -> IO WindowSize
checkStreamWindowSize
      where
        mtbq :: Maybe (TBQueue RspStreaming)
mtbq = Output -> Maybe (TBQueue RspStreaming)
outputStrmQ Output
out
        checkStreaming :: TBQueue a -> IO WindowSize
checkStreaming tbq :: TBQueue a
tbq = do
            Bool
isEmpty <- STM Bool -> IO Bool
forall a. STM a -> IO a
atomically (STM Bool -> IO Bool) -> STM Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ TBQueue a -> STM Bool
forall a. TBQueue a -> STM Bool
isEmptyTBQueue TBQueue a
tbq
            if Bool
isEmpty then do
                IO () -> PriorityTree Output -> Output -> Manager -> IO ()
forkAndEnqueueWhenReady (TBQueue a -> IO ()
forall a. TBQueue a -> IO ()
waitStreaming TBQueue a
tbq) PriorityTree Output
outputQ Output
out Manager
mgr
                WindowSize -> IO WindowSize
forall (m :: * -> *) a. Monad m => a -> m a
return WindowSize
off
              else
                IO WindowSize
checkStreamWindowSize
        checkStreamWindowSize :: IO WindowSize
checkStreamWindowSize = do
            WindowSize
sws <- Stream -> IO WindowSize
getStreamWindowSize Stream
strm
            if WindowSize
sws WindowSize -> WindowSize -> Bool
forall a. Eq a => a -> a -> Bool
== 0 then do
                IO () -> PriorityTree Output -> Output -> Manager -> IO ()
forkAndEnqueueWhenReady (Stream -> IO ()
waitStreamWindowSize Stream
strm) PriorityTree Output
outputQ Output
out Manager
mgr
                WindowSize -> IO WindowSize
forall (m :: * -> *) a. Monad m => a -> m a
return WindowSize
off
              else do
                WindowSize
cws <- TVar WindowSize -> IO WindowSize
forall a. TVar a -> IO a
readTVarIO TVar WindowSize
connectionWindow -- not 0
                let !lim :: WindowSize
lim = WindowSize -> WindowSize -> WindowSize
forall a. Ord a => a -> a -> a
min WindowSize
cws WindowSize
sws
                Output -> WindowSize -> WindowSize -> IO WindowSize
output Output
out WindowSize
off WindowSize
lim
        resetStream :: SomeException -> IO WindowSize
resetStream e :: SomeException
e = do
            Context -> Stream -> ClosedCode -> IO ()
closed Context
ctx Stream
strm (SomeException -> ClosedCode
ResetByMe SomeException
e)
            let !rst :: ByteString
rst = ErrorCodeId -> WindowSize -> ByteString
resetFrame ErrorCodeId
InternalError (WindowSize -> ByteString) -> WindowSize -> ByteString
forall a b. (a -> b) -> a -> b
$ Stream -> WindowSize
streamNumber Stream
strm
            TQueue Control -> Control -> IO ()
enqueueControl TQueue Control
controlQ (Control -> IO ()) -> Control -> IO ()
forall a b. (a -> b) -> a -> b
$ ByteString -> Control
CFrame ByteString
rst
            WindowSize -> IO WindowSize
forall (m :: * -> *) a. Monad m => a -> m a
return WindowSize
off

    {-# INLINE flushN #-}
    -- Flush the connection buffer to the socket, where the first 'n' bytes of
    -- the buffer are filled.
    flushN :: Int -> IO ()
    flushN :: WindowSize -> IO ()
flushN n :: WindowSize
n = Buffer -> WindowSize -> (ByteString -> IO ()) -> IO ()
forall a. Buffer -> WindowSize -> (ByteString -> IO a) -> IO a
bufferIO Buffer
confWriteBuffer WindowSize
n ByteString -> IO ()
confSendAll

    headerContinue :: WindowSize
-> TokenHeaderList -> Bool -> WindowSize -> IO WindowSize
headerContinue sid :: WindowSize
sid ths :: TokenHeaderList
ths endOfStream :: Bool
endOfStream off :: WindowSize
off = do
        let !offkv :: WindowSize
offkv = WindowSize
off WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+ WindowSize
frameHeaderLength
        let !bufkv :: Ptr b
bufkv = Buffer
confWriteBuffer Buffer -> WindowSize -> Ptr b
forall a b. Ptr a -> WindowSize -> Ptr b
`plusPtr` WindowSize
offkv
            !limkv :: WindowSize
limkv = WindowSize
confBufferSize WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
- WindowSize
offkv
        (hs :: TokenHeaderList
hs,kvlen :: WindowSize
kvlen) <- Context
-> Buffer
-> WindowSize
-> TokenHeaderList
-> IO (TokenHeaderList, WindowSize)
hpackEncodeHeader Context
ctx Buffer
forall b. Ptr b
bufkv WindowSize
limkv TokenHeaderList
ths
        let flag0 :: FrameFlags
flag0 = case TokenHeaderList
hs of
                [] -> FrameFlags -> FrameFlags
setEndHeader FrameFlags
defaultFlags
                _  -> FrameFlags
defaultFlags
            flag :: FrameFlags
flag = if Bool
endOfStream then FrameFlags -> FrameFlags
setEndStream FrameFlags
flag0 else FrameFlags
flag0
        let buf :: Ptr b
buf = Buffer
confWriteBuffer Buffer -> WindowSize -> Ptr b
forall a b. Ptr a -> WindowSize -> Ptr b
`plusPtr` WindowSize
off
        FrameTypeId
-> WindowSize -> WindowSize -> FrameFlags -> Buffer -> IO ()
fillFrameHeader FrameTypeId
FrameHeaders WindowSize
kvlen WindowSize
sid FrameFlags
flag Buffer
forall b. Ptr b
buf
        WindowSize -> WindowSize -> TokenHeaderList -> IO WindowSize
continue WindowSize
sid WindowSize
kvlen TokenHeaderList
hs

    !bufHeaderPayload :: Ptr b
bufHeaderPayload = Buffer
confWriteBuffer Buffer -> WindowSize -> Ptr b
forall a b. Ptr a -> WindowSize -> Ptr b
`plusPtr` WindowSize
frameHeaderLength
    !headerPayloadLim :: WindowSize
headerPayloadLim = WindowSize
confBufferSize WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
- WindowSize
frameHeaderLength

    continue :: WindowSize -> WindowSize -> TokenHeaderList -> IO WindowSize
continue _   kvlen :: WindowSize
kvlen [] = WindowSize -> IO WindowSize
forall (m :: * -> *) a. Monad m => a -> m a
return WindowSize
kvlen
    continue sid :: WindowSize
sid kvlen :: WindowSize
kvlen ths :: TokenHeaderList
ths = do
        WindowSize -> IO ()
flushN (WindowSize -> IO ()) -> WindowSize -> IO ()
forall a b. (a -> b) -> a -> b
$ WindowSize
kvlen WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+ WindowSize
frameHeaderLength
        -- Now off is 0
        (ths' :: TokenHeaderList
ths', kvlen' :: WindowSize
kvlen') <- Context
-> Buffer
-> WindowSize
-> TokenHeaderList
-> IO (TokenHeaderList, WindowSize)
hpackEncodeHeaderLoop Context
ctx Buffer
forall b. Ptr b
bufHeaderPayload WindowSize
headerPayloadLim TokenHeaderList
ths
        Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (TokenHeaderList
ths TokenHeaderList -> TokenHeaderList -> Bool
forall a. Eq a => a -> a -> Bool
== TokenHeaderList
ths') (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ HTTP2Error -> IO ()
forall e a. Exception e => e -> IO a
E.throwIO (HTTP2Error -> IO ()) -> HTTP2Error -> IO ()
forall a b. (a -> b) -> a -> b
$ ErrorCodeId -> ByteString -> HTTP2Error
ConnectionError ErrorCodeId
CompressionError "cannot compress the header"
        let flag :: FrameFlags
flag = case TokenHeaderList
ths' of
                [] -> FrameFlags -> FrameFlags
setEndHeader FrameFlags
defaultFlags
                _  -> FrameFlags
defaultFlags
        FrameTypeId
-> WindowSize -> WindowSize -> FrameFlags -> Buffer -> IO ()
fillFrameHeader FrameTypeId
FrameContinuation WindowSize
kvlen' WindowSize
sid FrameFlags
flag Buffer
confWriteBuffer
        WindowSize -> WindowSize -> TokenHeaderList -> IO WindowSize
continue WindowSize
sid WindowSize
kvlen' TokenHeaderList
ths'

    {-# INLINE sendHeadersIfNecessary #-}
    -- Send headers if there is not room for a 1-byte data frame, and return
    -- the offset of the next frame's first header byte.
    sendHeadersIfNecessary :: WindowSize -> IO WindowSize
sendHeadersIfNecessary off :: WindowSize
off
      -- True if the connection buffer has room for a 1-byte data frame.
      | WindowSize
off WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+ WindowSize
frameHeaderLength WindowSize -> WindowSize -> Bool
forall a. Ord a => a -> a -> Bool
< WindowSize
confBufferSize = WindowSize -> IO WindowSize
forall (m :: * -> *) a. Monad m => a -> m a
return WindowSize
off
      | Bool
otherwise = do
          WindowSize -> IO ()
flushN WindowSize
off
          WindowSize -> IO WindowSize
forall (m :: * -> *) a. Monad m => a -> m a
return 0

    fillDataHeaderEnqueueNext :: Stream
-> WindowSize
-> WindowSize
-> Maybe DynaNext
-> TrailersMaker
-> IO a
-> Output
-> IO WindowSize
fillDataHeaderEnqueueNext strm :: Stream
strm@Stream{TVar WindowSize
streamWindow :: TVar WindowSize
streamWindow :: Stream -> TVar WindowSize
streamWindow,WindowSize
streamNumber :: WindowSize
streamNumber :: Stream -> WindowSize
streamNumber}
                   off :: WindowSize
off datPayloadLen :: WindowSize
datPayloadLen Nothing tlrmkr :: TrailersMaker
tlrmkr tell :: IO a
tell _ = do
        let !buf :: Ptr b
buf  = Buffer
confWriteBuffer Buffer -> WindowSize -> Ptr b
forall a b. Ptr a -> WindowSize -> Ptr b
`plusPtr` WindowSize
off
            !off' :: WindowSize
off' = WindowSize
off WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+ WindowSize
frameHeaderLength WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+ WindowSize
datPayloadLen
        (mtrailers :: Maybe ResponseHeaders
mtrailers, flag :: FrameFlags
flag) <- do
              Trailers !ResponseHeaders
trailers <- TrailersMaker
tlrmkr Maybe ByteString
forall a. Maybe a
Nothing
              if ResponseHeaders -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ResponseHeaders
trailers then
                  (Maybe ResponseHeaders, FrameFlags)
-> IO (Maybe ResponseHeaders, FrameFlags)
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe ResponseHeaders
forall a. Maybe a
Nothing, FrameFlags -> FrameFlags
setEndStream FrameFlags
defaultFlags)
                else
                  (Maybe ResponseHeaders, FrameFlags)
-> IO (Maybe ResponseHeaders, FrameFlags)
forall (m :: * -> *) a. Monad m => a -> m a
return (ResponseHeaders -> Maybe ResponseHeaders
forall a. a -> Maybe a
Just ResponseHeaders
trailers, FrameFlags
defaultFlags)
        FrameTypeId
-> WindowSize -> WindowSize -> FrameFlags -> Buffer -> IO ()
fillFrameHeader FrameTypeId
FrameData WindowSize
datPayloadLen WindowSize
streamNumber FrameFlags
flag Buffer
forall b. Ptr b
buf
        WindowSize
off'' <- Maybe ResponseHeaders -> WindowSize -> IO WindowSize
handleTrailers Maybe ResponseHeaders
mtrailers WindowSize
off'
        IO a -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void IO a
tell
        Context -> Stream -> ClosedCode -> IO ()
halfClosedLocal Context
ctx Stream
strm ClosedCode
Finished
        STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ TVar WindowSize -> (WindowSize -> WindowSize) -> STM ()
forall a. TVar a -> (a -> a) -> STM ()
modifyTVar' TVar WindowSize
connectionWindow (WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
subtract WindowSize
datPayloadLen)
        STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ TVar WindowSize -> (WindowSize -> WindowSize) -> STM ()
forall a. TVar a -> (a -> a) -> STM ()
modifyTVar' TVar WindowSize
streamWindow (WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
subtract WindowSize
datPayloadLen)
        WindowSize -> IO WindowSize
forall (m :: * -> *) a. Monad m => a -> m a
return WindowSize
off''
      where
        handleTrailers :: Maybe ResponseHeaders -> WindowSize -> IO WindowSize
handleTrailers Nothing off0 :: WindowSize
off0 = WindowSize -> IO WindowSize
forall (m :: * -> *) a. Monad m => a -> m a
return WindowSize
off0
        handleTrailers (Just trailers :: ResponseHeaders
trailers) off0 :: WindowSize
off0 = do
            (ths :: TokenHeaderList
ths,_) <- ResponseHeaders -> IO (TokenHeaderList, ValueTable)
toHeaderTable ResponseHeaders
trailers
            WindowSize
kvlen <- WindowSize
-> TokenHeaderList -> Bool -> WindowSize -> IO WindowSize
headerContinue WindowSize
streamNumber TokenHeaderList
ths Bool
True WindowSize
off0
            WindowSize -> IO WindowSize
sendHeadersIfNecessary (WindowSize -> IO WindowSize) -> WindowSize -> IO WindowSize
forall a b. (a -> b) -> a -> b
$ WindowSize
off0 WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+ WindowSize
frameHeaderLength WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+ WindowSize
kvlen

    fillDataHeaderEnqueueNext Stream{TVar WindowSize
streamWindow :: TVar WindowSize
streamWindow :: Stream -> TVar WindowSize
streamWindow,WindowSize
streamNumber :: WindowSize
streamNumber :: Stream -> WindowSize
streamNumber}
                   off :: WindowSize
off datPayloadLen :: WindowSize
datPayloadLen (Just next :: DynaNext
next) tlrmkr :: TrailersMaker
tlrmkr _ out :: Output
out = do
        let !buf :: Ptr b
buf  = Buffer
confWriteBuffer Buffer -> WindowSize -> Ptr b
forall a b. Ptr a -> WindowSize -> Ptr b
`plusPtr` WindowSize
off
            !off' :: WindowSize
off' = WindowSize
off WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+ WindowSize
frameHeaderLength WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+ WindowSize
datPayloadLen
            flag :: FrameFlags
flag  = FrameFlags
defaultFlags
        FrameTypeId
-> WindowSize -> WindowSize -> FrameFlags -> Buffer -> IO ()
fillFrameHeader FrameTypeId
FrameData WindowSize
datPayloadLen WindowSize
streamNumber FrameFlags
flag Buffer
forall b. Ptr b
buf
        STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ TVar WindowSize -> (WindowSize -> WindowSize) -> STM ()
forall a. TVar a -> (a -> a) -> STM ()
modifyTVar' TVar WindowSize
connectionWindow (WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
subtract WindowSize
datPayloadLen)
        STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ TVar WindowSize -> (WindowSize -> WindowSize) -> STM ()
forall a. TVar a -> (a -> a) -> STM ()
modifyTVar' TVar WindowSize
streamWindow (WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
subtract WindowSize
datPayloadLen)
        let !out' :: Output
out' = Output
out { outputType :: OutputType
outputType = DynaNext -> TrailersMaker -> OutputType
ONext DynaNext
next TrailersMaker
tlrmkr }
        PriorityTree Output -> Output -> IO ()
enqueueOutput PriorityTree Output
outputQ Output
out'
        WindowSize -> IO WindowSize
forall (m :: * -> *) a. Monad m => a -> m a
return WindowSize
off'

    pushPromise :: WindowSize -> a -> TokenHeaderList -> WindowSize -> IO WindowSize
pushPromise pid :: WindowSize
pid sid :: a
sid ths :: TokenHeaderList
ths off :: WindowSize
off = do
        let !offsid :: WindowSize
offsid = WindowSize
off WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+ WindowSize
frameHeaderLength
            !bufsid :: Ptr b
bufsid = Buffer
confWriteBuffer Buffer -> WindowSize -> Ptr b
forall a b. Ptr a -> WindowSize -> Ptr b
`plusPtr` WindowSize
offsid
        Word32 -> Buffer -> WindowSize -> IO ()
poke32 (a -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
sid) Buffer
forall b. Ptr b
bufsid 0
        let !offkv :: WindowSize
offkv  = WindowSize
offsid WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+ 4
            !bufkv :: Ptr b
bufkv  = Buffer
confWriteBuffer Buffer -> WindowSize -> Ptr b
forall a b. Ptr a -> WindowSize -> Ptr b
`plusPtr` WindowSize
offkv
            !limkv :: WindowSize
limkv  = WindowSize
confBufferSize WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
- WindowSize
offkv
        (_,kvlen :: WindowSize
kvlen) <- Context
-> Buffer
-> WindowSize
-> TokenHeaderList
-> IO (TokenHeaderList, WindowSize)
hpackEncodeHeader Context
ctx Buffer
forall b. Ptr b
bufkv WindowSize
limkv TokenHeaderList
ths
        let !flag :: FrameFlags
flag = FrameFlags -> FrameFlags
setEndHeader FrameFlags
defaultFlags -- No EndStream flag
            !buf :: Ptr b
buf = Buffer
confWriteBuffer Buffer -> WindowSize -> Ptr b
forall a b. Ptr a -> WindowSize -> Ptr b
`plusPtr` WindowSize
off
            !len :: WindowSize
len = WindowSize
kvlen WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+ 4
        FrameTypeId
-> WindowSize -> WindowSize -> FrameFlags -> Buffer -> IO ()
fillFrameHeader FrameTypeId
FramePushPromise WindowSize
len WindowSize
pid FrameFlags
flag Buffer
forall b. Ptr b
buf
        WindowSize -> IO WindowSize
forall (m :: * -> *) a. Monad m => a -> m a
return WindowSize
len

    {-# INLINE fillFrameHeader #-}
    fillFrameHeader :: FrameTypeId
-> WindowSize -> WindowSize -> FrameFlags -> Buffer -> IO ()
fillFrameHeader ftyp :: FrameTypeId
ftyp len :: WindowSize
len sid :: WindowSize
sid flag :: FrameFlags
flag buf :: Buffer
buf = FrameTypeId -> FrameHeader -> Buffer -> IO ()
encodeFrameHeaderBuf FrameTypeId
ftyp FrameHeader
hinfo Buffer
buf
      where
        hinfo :: FrameHeader
hinfo = WindowSize -> FrameFlags -> WindowSize -> FrameHeader
FrameHeader WindowSize
len FrameFlags
flag WindowSize
sid

    runTrailersMaker :: (Maybe ByteString -> IO a) -> WindowSize -> WindowSize -> IO a
runTrailersMaker tlrmkr :: Maybe ByteString -> IO a
tlrmkr off :: WindowSize
off siz :: WindowSize
siz = do
        let datBuf :: Ptr b
datBuf = Buffer
confWriteBuffer Buffer -> WindowSize -> Ptr b
forall a b. Ptr a -> WindowSize -> Ptr b
`plusPtr` WindowSize
off
        Buffer -> WindowSize -> (ByteString -> IO a) -> IO a
forall a. Buffer -> WindowSize -> (ByteString -> IO a) -> IO a
bufferIO Buffer
forall b. Ptr b
datBuf WindowSize
siz ((ByteString -> IO a) -> IO a) -> (ByteString -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \bs :: ByteString
bs -> Maybe ByteString -> IO a
tlrmkr (ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
bs)

    {-# INLINE ignore #-}
    ignore :: E.SomeException -> IO ()
    ignore :: SomeException -> IO ()
ignore _ = () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

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

fillBuilderBodyGetNext :: Config -> Int -> WindowSize -> Builder -> IO Next
fillBuilderBodyGetNext :: Config -> WindowSize -> WindowSize -> Builder -> IO Next
fillBuilderBodyGetNext Config{Buffer
confWriteBuffer :: Buffer
confWriteBuffer :: Config -> Buffer
confWriteBuffer,WindowSize
confBufferSize :: WindowSize
confBufferSize :: Config -> WindowSize
confBufferSize}
                       off :: WindowSize
off lim :: WindowSize
lim bb :: Builder
bb = do
    let datBuf :: Ptr b
datBuf = Buffer
confWriteBuffer Buffer -> WindowSize -> Ptr b
forall a b. Ptr a -> WindowSize -> Ptr b
`plusPtr` WindowSize
off
        room :: WindowSize
room = WindowSize -> WindowSize -> WindowSize
forall a. Ord a => a -> a -> a
min (WindowSize
confBufferSize WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
- WindowSize
off) WindowSize
lim
    (len :: WindowSize
len, signal :: Next
signal) <- Builder -> BufferWriter
B.runBuilder Builder
bb Buffer
forall b. Ptr b
datBuf WindowSize
room
    Next -> IO Next
forall (m :: * -> *) a. Monad m => a -> m a
return (Next -> IO Next) -> Next -> IO Next
forall a b. (a -> b) -> a -> b
$ WindowSize -> Next -> Next
nextForBuilder WindowSize
len Next
signal

fillFileBodyGetNext :: Config -> Int -> WindowSize -> FilePath -> FileOffset -> ByteCount -> Manager -> PositionReadMaker -> IO Next
fillFileBodyGetNext :: Config
-> WindowSize
-> WindowSize
-> FilePath
-> FileOffset
-> FileOffset
-> Manager
-> PositionReadMaker
-> IO Next
fillFileBodyGetNext Config{Buffer
confWriteBuffer :: Buffer
confWriteBuffer :: Config -> Buffer
confWriteBuffer,WindowSize
confBufferSize :: WindowSize
confBufferSize :: Config -> WindowSize
confBufferSize}
                    off :: WindowSize
off lim :: WindowSize
lim path :: FilePath
path start :: FileOffset
start bytecount :: FileOffset
bytecount mgr :: Manager
mgr prmaker :: PositionReadMaker
prmaker = do
    let datBuf :: Ptr b
datBuf = Buffer
confWriteBuffer Buffer -> WindowSize -> Ptr b
forall a b. Ptr a -> WindowSize -> Ptr b
`plusPtr` WindowSize
off
        room :: WindowSize
room = WindowSize -> WindowSize -> WindowSize
forall a. Ord a => a -> a -> a
min (WindowSize
confBufferSize WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
- WindowSize
off) WindowSize
lim
    (pread :: PositionRead
pread, sentinel :: Sentinel
sentinel) <- PositionReadMaker
prmaker FilePath
path
    IO ()
checkPriority  class="annottext">Window id="line-244">      )
FrameHeader{FrameFlags
flags :: FrameFlags
flags :: FrameHeader -> FrameFlags
renewOtherRevIndex -> http2settings, TQueue Control
controlQ :: TQueue Control
controlQ :olothing, 7
-> 1679120004">TQueue Control
controlQ :: TQueue Control
controlQ :olothingB
TQspan class="annot">rtnewOtherRevIndex -> ">WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
+-> outputQ
            if Bool
emp<53pan>ba><53pan>ba><53pan>ba><53pan>ba><53pan>ba><53pan>ba><53pan>ba><53pan>ba><53pan>ba><53pan>ba><53pan>ba><53pan>ba><53pan>ba><53pan><53pan>ba><53checkPriority  class="annottext">Window id="line-244">      tokenAcceptCharsettokenAcceptCharset
checkPriority  class="annottext">Window id="line-244"> ntifier hs-var">readTVarIO readTVarIOtext">BufferSize
streamNumbertext">BufferSize
streamNumbertext">BufferSize
streamNumbertext">BufferSize
streamNumbertext">BufferSize
= IO WindowSize
forall a. HasCa class="hs-idespaP>  n class="hs-glyph">= WindowSize -> WindowSize -> WindowSize
forall a. Ord a => a -7gt; a -> a
min (WindowSize
confBufferSize min ByteString
bs
    !timeoutKillThread :: timeoutKillThread :: timeoutKillThread :: timeoutO FramePayload
forall a b. (a -> b) -> a -> b
fillDataHeaePayload
forall a b. (a -> b) -> a -> b
processStreamGuardingError FilePath
FilePath
a ->  :: timeoutKillThread streamNumbertext">BufferSize
 Bufrse t, Eq a) => a -> t a -> Bool
me
state :: (IOBnb, b)
inc2
(IOBnb, b)
inc2-> outputQ
             -> outputQ
IOBnb, b)
inc2+ 4
        Context
ctx :: pid
IOBnb, b)
inc2+inc2dequeue
  ,off0 :: WindowSize
 Config{Buffer
confWriteBuffka :: Buffer
confWriteBuffer :: Config -> Buffer
Context
Context
FrameHeader
}
  lass="annot">fillDataHeaePayload
forall a b. (a -> b) -> a -> b
<pan> 0
< classan 
  ,off0 :: WindowSize
 0
< classan 
 Bufrse t, Eq a) => a -> t a -> Bool
me
FrameHeader
state :: ((HTTP2Error -> IO ()) -> HTTP2Error -> IO ()
forall a b. (a -> b) -> a -> b
6">n :: BufferSize
(HTTP2Erroranno#loc>datBu-# INLeNE (HTTP2Erroranno#loc>datBu-# INLeNE datBu-# INLeNE (HTTP2Erroranno#loc>datBu-#WindowSize
kvlen kvlen kvlen44o#loef="#lhref="#local-6989586621679119404">datPayloadLenkvlen44o#loef="#lhref="#local-6989586621679119404">datPayloadLenout'  class="annottext">Window id="line-244"> ntifier hs-var">readTVarIO qualified Data 6M ()
tifier mtBrd">qpan>Window id="line-244"> ntifier hs-var">readTVarIO qumsref="#l69/sn clid="locspanan>  ntifier hs-var">rpan>VarIO qumsref="#l69/sn clid="locspanan>  ntifier hs-var">rpan>VarIO  <>
  , just
  , (HTTP2Erroranno#loc>datBu-# INLeNE qumsref="#l69/sn clid="locspanan>  ntifier hs-va-6989586621679116804">tid (HTTP2Erroran> (HTTP2Erroran> ,off0 :: WindowSize
 ize79115/span>,off0 :: WindowSize
,of class="annottext">queue' :: Heap a
queue' ntifier hs-va-6989586621679116804">tid timeoutKillThread  timeoutKillThread  an> an> an> {FrameHeader{BufferSize
streamId ml#T">T,{off
      |       |       |       |       TVar W|       |       |       TVar W| , Bool
False)
   ph">|<7las/span>      Window id="line-244"> ntifier hs-var">readTVarIO ByteString -> Bool
B.null < hs-var">B.n>                      WindowSize -> WindowSize -> WindowSize
fora"7 r hsass="annotn>ss=n class="annotn> WindowSiz 3lass="hs-not"> WindowSize -> WindowSize -> WindowSize
fora"7 r hsspan class="annot">WindowSize -> H;ndowSize -> WindowSize
fora"7 r hsspan clasdowSize
fora"7 r hsspan class="annot">WindowSize -> H;ndowSizeotn> WindowSize -> WindowSize -> WindowSize
fora"7 r hsass="annotn>ss=n class="annotn> WindowSize -> WindowSize -> WindowSize
fora"7 r hsass="annotn>ss=n class="annotn>span class="an0ƒt">WindowSize -> WindowSize -> WindowSize
fora"7 r hsass="annotn>ss=n class="annotn>span classpan class="annot">WindowSize -> WindowSize -> WindowSize
fora"7 r hsass="ann21679120090">strm (mntuest -> Input) -&g444444444444444444444444444444444444444424444444103T444444444444444444444444444444444444444403T44444tuest -> Input) -&g444444444444444444444444444444444444444424444444103T444444444444444444444444444444444444444403T44444tue4444444444443ef="Network.HTTP2.Server.API.html#PositionReadMakeresPositionReteMaker ->|       strm dowSiz>(mntuest -> Input) -&g444444444444444444444444444444444444444424444444103T444444444444444444444444444444444444444403T44444tuest -> Input) -&g444444444444444444444444444444444444444424444444103T44444444444444444444444444444n>34144444444444444444444424444444103T444444444444444444444444444444444444444403T44444tuest -> Input) -&g444444444444444444444444444444444444444424444444103T44444444444444444444444444444n>nnot">WindowSize
WinindowSize
kvlen eStrin classwork.HTTP2.Server/span>
< classan 
 Bufrse t, Eq a) => a -> t a -> Bool
me34>Bu -> Bufrse t, Eq a) => a -> t a -> Bool
n :: BufferSize
Bufrse t, Eq a) => a -> t a -> Bool
n :: BufferSize
Bufrse t, Eq a) => a -> t 2633ref="#lltrm Window id="rlnss="hs-glyph">= case  Window id="rlnss="hs-glyph">= case  Window id="rlnss="hs-glyph">= case  confBufferSize WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
- out { outputType :: OutputType
confBufferSize WindowSize -> WindowSize -> WindowSize
forall a. Num a => a -> a -> a
- out { outputType :: OutputType
outputTypver.QuutputTypException -> 7t">on> ntifier hs-va-6989586621679116804">tidon> ntifier hs-va-6989n>status
    (!!!ByteString
frame
r hs-var">False!Bpan class="annot">off0 :: WindowSize
,bufkv WinillThre2.SeSize
identifier hs-var">bufkv bufkv /span>    bufkv /span>    bufkvbufkvbufkvbufkvbufkvbufkvbufkvbufkvbufkvbufkvbufkvbufkvbufkvbufkspanss="annottext">e :: SomeException>bufkv<="ann21679120tifier hs-var">bufkspanss="annottext">e :: SomeException>bufkv<="ann21679120tifier hs-var">bufkspanss="annottext">e :: SomeException679119347">bufkspanss="annottext">e :: SomeException679119347">bufkv<="ann21679120tifier hs-var">bufkspanss="annottext">e ::)"anslides="annottext"