{-# LANGUAGE NamedFieldPuns #-}

module Network.HTTP2.Arch.Context where

import Control.Concurrent.STM
import Data.IORef
import Network.HTTP.Types (Method)

import Imports hiding (insert)
import Network.HPACK
import Network.HTTP2.Arch.Cache (Cache, emptyCache)
import qualified Network.HTTP2.Arch.Cache as Cache
import Network.HTTP2.Arch.Rate
import Network.HTTP2.Arch.Stream
import Network.HTTP2.Arch.Types
import Network.HTTP2.Frame

data Role = Client | Server deriving (Role -> Role -> Bool
(Role -> Role -> Bool) -> (Role -> Role -> Bool) -> Eq Role
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Role -> Role -> Bool
$c/= :: Role -> Role -> Bool
== :: Role -> Role -> Bool
$c== :: Role -> Role -> Bool
Eq,Int -> Role -> ShowS
[Role] -> ShowS
Role -> String
(Int -> Role -> ShowS)
-> (Role -> String) -> ([Role] -> ShowS) -> Show Role
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Role] -> ShowS
$cshowList :: [Role] -> ShowS
show :: Role -> String
$cshow :: Role -> String
showsPrec :: Int -> Role -> ShowS
$cshowsPrec :: Int -> Role -> ShowS
Show)

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

data RoleInfo = ServerInfo {
                    RoleInfo -> TQueue (Input Stream)
inputQ :: TQueue (Input Stream)
                  }
              | ClientInfo {
                    RoleInfo -> ByteString
scheme    :: ByteString
                  , RoleInfo -> ByteString
authority :: ByteString
                  , RoleInfo -> IORef (Cache (ByteString, ByteString) Stream)
cache     :: IORef (Cache (Method,ByteString) Stream)
                  }

newServerInfo :: IO RoleInfo
newServerInfo :: IO RoleInfo
newServerInfo = TQueue (Input Stream) -> RoleInfo
ServerInfo (TQueue (Input Stream) -> RoleInfo)
-> IO (TQueue (Input Stream)) -> IO RoleInfo
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO (TQueue (Input Stream))
forall a. IO (TQueue a)
newTQueueIO

newClientInfo :: ByteString -> ByteString -> Int -> IO RoleInfo
newClientInfo :: ByteString -> ByteString -> Int -> IO RoleInfo
newClientInfo ByteString
scm ByteString
auth Int
lim =  ByteString
-> ByteString
-> IORef (Cache (ByteString, ByteString) Stream)
-> RoleInfo
ClientInfo ByteString
scm ByteString
auth (IORef (Cache (ByteString, ByteString) Stream) -> RoleInfo)
-> IO (IORef (Cache (ByteString, ByteString) Stream))
-> IO RoleInfo
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Cache (ByteString, ByteString) Stream
-> IO (IORef (Cache (ByteString, ByteString) Stream))
forall a. a -> IO (IORef a)
newIORef (Int -> Cache (ByteString, ByteString) Stream
forall k v. Int -> Cache k v
emptyCache Int
lim)

insertCache :: Method -> ByteString -> Stream -> RoleInfo -> IO ()
insertCache :: ByteString -> ByteString -> Stream -> RoleInfo -> IO ()
insertCache ByteString
m ByteString
path Stream
v (ClientInfo ByteString
_ ByteString
_ IORef (Cache (ByteString, ByteString) Stream)
ref) = IORef (Cache (ByteString, ByteString) Stream)
-> (Cache (ByteString, ByteString) Stream
    -> (Cache (ByteString, ByteString) Stream, ()))
-> IO ()
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef' IORef (Cache (ByteString, ByteString) Stream)
ref ((Cache (ByteString, ByteString) Stream
  -> (Cache (ByteString, ByteString) Stream, ()))
 -> IO ())
-> (Cache (ByteString, ByteString) Stream
    -> (Cache (ByteString, ByteString) Stream, ()))
-> IO ()
forall a b. (a -> b) -> a -> b
$ \Cache (ByteString, ByteString) Stream
c ->
  ((ByteString, ByteString)
-> Stream
-> Cache (ByteString, ByteString) Stream
-> Cache (ByteString, ByteString) Stream
forall k v. Ord k => k -> v -> Cache k v -> Cache k v
Cache.insert (ByteString
m,ByteString
path) Stream
v Cache (ByteString, ByteString) Stream
c, ())
insertCache ByteString
_ ByteString
_ Stream
_ RoleInfo
_ = String -> IO ()
forall a. HasCallStack => String -> a
error String
"insertCache"

lookupCache :: Method -> ByteString -> RoleInfo -> IO (Maybe Stream)
lookupCache :: ByteString -> ByteString -> RoleInfo -> IO (Maybe Stream)
lookupCache ByteString
m ByteString
path (ClientInfo ByteString
_ ByteString
_ IORef (Cache (ByteString, ByteString) Stream)
ref) = (ByteString, ByteString)
-> Cache (ByteString, ByteString) Stream -> Maybe Stream
forall k v. Ord k => k -> Cache k v -> Maybe v
Cache.lookup (ByteString
m,ByteString
path) (Cache (ByteString, ByteString) Stream -> Maybe Stream)
-> IO (Cache (ByteString, ByteString) Stream) -> IO (Maybe Stream)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IORef (Cache (ByteString, ByteString) Stream)
-> IO (Cache (ByteString, ByteString) Stream)
forall a. IORef a -> IO a
readIORef IORef (Cache (ByteString, ByteString) Stream)
ref
lookupCache ByteString
_ ByteString
_ RoleInfo
_ = String -> IO (Maybe Stream)
forall a. HasCallStack => String -> a
error String
"lookupCache"

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

-- | The context for HTTP/2 connection.
data Context = Context {
    Context -> Role
role               :: Role
  , Context -> RoleInfo
roleInfo           :: RoleInfo
  -- HTTP/2 settings received from a browser
  , Context -> IORef Settings
http2settings      :: IORef Settings
  , Context -> IORef Bool
firstSettings      :: IORef Bool
  , Context -> StreamTable
streamTable        :: StreamTable
  , Context -> IORef Int
concurrency        :: IORef Int
  -- | RFC 7540 says "Other frames (from any stream) MUST NOT
  --   occur between the HEADERS frame and any CONTINUATION
  --   frames that might follow". This field is used to implement
  --   this requirement.
  , Context -> IORef (Maybe Int)
continued          :: IORef (Maybe StreamId)
  , Context -> IORef Int
myStreamId         :: IORef StreamId
  , Context -> IORef Int
peerStreamId       :: IORef StreamId
  , Context -> TQueue (Output Stream)
outputQ            :: TQueue (Output Stream)
  , Context -> TQueue Control
controlQ           :: TQueue Control
  , Context -> DynamicTable
encodeDynamicTable :: DynamicTable
  , Context -> DynamicTable
decodeDynamicTable :: DynamicTable
  -- the connection window for data from a server to a browser.
  , Context -> TVar Int
connectionWindow   :: TVar WindowSize
  , Context -> Rate
pingRate           :: Rate
  , Context -> Rate
settingsRate       :: Rate
  , Context -> Rate
emptyFrameRate     :: Rate
  }

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

newContext :: RoleInfo -> IO Context
newContext :: RoleInfo -> IO Context
newContext RoleInfo
rinfo =
    Role
-> RoleInfo
-> IORef Settings
-> IORef Bool
-> StreamTable
-> IORef Int
-> IORef (Maybe Int)
-> IORef Int
-> IORef Int
-> TQueue (Output Stream)
-> TQueue Control
-> DynamicTable
-> DynamicTable
-> TVar Int
-> Rate
-> Rate
-> Rate
-> Context
Context Role
rl RoleInfo
rinfo
               (IORef Settings
 -> IORef Bool
 -> StreamTable
 -> IORef Int
 -> IORef (Maybe Int)
 -> IORef Int
 -> IORef Int
 -> TQueue (Output Stream)
 -> TQueue Control
 -> DynamicTable
 -> DynamicTable
 -> TVar Int
 -> Rate
 -> Rate
 -> Rate
 -> Context)
-> IO (IORef Settings)
-> IO
     (IORef Bool
      -> StreamTable
      -> IORef Int
      -> IORef (Maybe Int)
      -> IORef Int
      -> IORef Int
      -> TQueue (Output Stream)
      -> TQueue Control
      -> DynamicTable
      -> DynamicTable
      -> TVar Int
      -> Rate
      -> Rate
      -> Rate
      -> Context)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Settings -> IO (IORef Settings)
forall a. a -> IO (IORef a)
newIORef Settings
defaultSettings
               IO
  (IORef Bool
   -> StreamTable
   -> IORef Int
   -> IORef (Maybe Int)
   -> IORef Int
   -> IORef Int
   -> TQueue (Output Stream)
   -> TQueue Control
   -> DynamicTable
   -> DynamicTable
   -> TVar Int
   -> Rate
   -> Rate
   -> Rate
   -> Context)
-> IO (IORef Bool)
-> IO
     (StreamTable
      -> IORef Int
      -> IORef (Maybe Int)
      -> IORef Int
      -> IORef Int
      -> TQueue (Output Stream)
      -> TQueue Control
      -> DynamicTable
      -> DynamicTable
      -> TVar Int
      -> Rate
      -> Rate
      -> Rate
      -> Context)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Bool -> IO (IORef Bool)
forall a. a -> IO (IORef a)
newIORef Bool
False
               IO
  (StreamTable
   -> IORef Int
   -> IORef (Maybe Int)
   -> IORef Int
   -> IORef Int
   -> TQueue (Output Stream)
   -> TQueue Control
   -> DynamicTable
   -> DynamicTable
   -> TVar Int
   -> Rate
   -> Rate
   -> Rate
   -> Context)
-> IO StreamTable
-> IO
     (IORef Int
      -> IORef (Maybe Int)
      -> IORef Int
      -> IORef Int
      -> TQueue (Output Stream)
      -> TQueue Control
      -> DynamicTable
      -> DynamicTable
      -> TVar Int
      -> Rate
      -> Rate
      -> Rate
      -> Context)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> IO StreamTable
newStreamTable
               IO
  (IORef Int
   -> IORef (Maybe Int)
   -> IORef Int
   -> IORef Int
   -> TQueue (Output Stream)
   -> TQueue Control
   -> DynamicTable
   -> DynamicTable
   -> TVar Int
   -> Rate
   -> Rate
   -> Rate
   -> Context)
-> IO (IORef Int)
-> IO
     (IORef (Maybe Int)
      -> IORef Int
      -> IORef Int
      -> TQueue (Output Stream)
      -> TQueue Control
      -> DynamicTable
      -> DynamicTable
      -> TVar Int
      -> Rate
      -> Rate
      -> Rate
      -> Context)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> IO (IORef Int)
forall a. a -> IO (IORef a)
newIORef Int
0
               IO
  (IORef (Maybe Int)
   -> IORef Int
   -> IORef Int
   -> TQueue (Output Stream)
   -> TQueue Control
   -> DynamicTable
   -> DynamicTable
   -> TVar Int
   -> Rate
   -> Rate
   -> Rate
   -> Context)
-> IO (IORef (Maybe Int))
-> IO
     (IORef Int
      -> IORef Int
      -> TQueue (Output Stream)
      -> TQueue Control
      -> DynamicTable
      -> DynamicTable
      -> TVar Int
      -> Rate
      -> Rate
      -> Rate
      -> Context)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe Int -> IO (IORef (Maybe Int))
forall a. a -> IO (IORef a)
newIORef Maybe Int
forall a. Maybe a
Nothing
               IO
  (IORef Int
   -> IORef Int
   -> TQueue (Output Stream)
   -> TQueue Control
   -> DynamicTable
   -> DynamicTable
   -> TVar Int
   -> Rate
   -> Rate
   -> Rate
   -> Context)
-> IO (IORef Int)
-> IO
     (IORef Int
      -> TQueue (Output Stream)
      -> TQueue Control
      -> DynamicTable
      -> DynamicTable
      -> TVar Int
      -> Rate
      -> Rate
      -> Rate
      -> Context)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> IO (IORef Int)
forall a. a -> IO (IORef a)
newIORef Int
sid0
               IO
  (IORef Int
   -> TQueue (Output Stream)
   -> TQueue Control
   -> DynamicTable
   -> DynamicTable
   -> TVar Int
   -> Rate
   -> Rate
   -> Rate
   -> Context)
-> IO (IORef Int)
-> IO
     (TQueue (Output Stream)
      -> TQueue Control
      -> DynamicTable
      -> DynamicTable
      -> TVar Int
      -> Rate
      -> Rate
      -> Rate
      -> Context)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> IO (IORef Int)
forall a. a -> IO (IORef a)
newIORef Int
0
               IO
  (TQueue (Output Stream)
   -> TQueue Control
   -> DynamicTable
   -> DynamicTable
   -> TVar Int
   -> Rate
   -> Rate
   -> Rate
   -> Context)
-> IO (TQueue (Output Stream))
-> IO
     (TQueue Control
      -> DynamicTable
      -> DynamicTable
      -> TVar Int
      -> Rate
      -> Rate
      -> Rate
      -> Context)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> IO (TQueue (Output Stream))
forall a. IO (TQueue a)
newTQueueIO
               IO
  (TQueue Control
   -> DynamicTable
   -> DynamicTable
   -> TVar Int
   -> Rate
   -> Rate
   -> Rate
   -> Context)
-> IO (TQueue Control)
-> IO
     (DynamicTable
      -> DynamicTable -> TVar Int -> Rate -> Rate -> Rate -> Context)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> IO (TQueue Control)
forall a. IO (TQueue a)
newTQueueIO
               IO
  (DynamicTable
   -> DynamicTable -> TVar Int -> Rate -> Rate -> Rate -> Context)
-> IO DynamicTable
-> IO (DynamicTable -> TVar Int -> Rate -> Rate -> Rate -> Context)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> IO DynamicTable
newDynamicTableForEncoding Int
defaultDynamicTableSize
               IO (DynamicTable -> TVar Int -> Rate -> Rate -> Rate -> Context)
-> IO DynamicTable
-> IO (TVar Int -> Rate -> Rate -> Rate -> Context)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> Int -> IO DynamicTable
newDynamicTableForDecoding Int
defaultDynamicTableSize Int
4096
               IO (TVar Int -> Rate -> Rate -> Rate -> Context)
-> IO (TVar Int) -> IO (Rate -> Rate -> Rate -> Context)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> IO (TVar Int)
forall a. a -> IO (TVar a)
newTVarIO Int
defaultInitialWindowSize
               IO (Rate -> Rate -> Rate -> Context)
-> IO Rate -> IO (Rate -> Rate -> Context)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> IO Rate
newRate
               IO (Rate -> Rate -> Context) -> IO Rate -> IO (Rate -> Context)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> IO Rate
newRate
               IO (Rate -> Context) -> IO Rate -> IO Context
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> IO Rate
newRate
   where
     rl :: Role
rl = case RoleInfo
rinfo of
       ClientInfo{} -> Role
Client
       RoleInfo
_            -> Role
Server
     sid0 :: Int
sid0 | Role
rl Role -> Role -> Bool
forall a. Eq a => a -> a -> Bool
== Role
Client = Int
1
          | Bool
otherwise    = Int
2

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

isClient :: Context -> Bool
isClient :: Context -> Bool
isClient Context
ctx = Context -> Role
role Context
ctx Role -> Role -> Bool
forall a. Eq a => a -> a -> Bool
== Role
Client

isServer :: Context -> Bool
isServer :: Context -> Bool
isServer Context
ctx = Context -> Role
role Context
ctx Role -> Role -> Bool
forall a. Eq a => a -> a -> Bool
== Role
Server

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

getMyNewStreamId :: Context -> IO StreamId
getMyNewStreamId :: Context -> IO Int
getMyNewStreamId Context
ctx = IORef Int -> (Int -> (Int, Int)) -> IO Int
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef' (Context -> IORef Int
myStreamId Context
ctx) Int -> (Int, Int)
forall a. Num a => a -> (a, a)
inc2
  where
    inc2 :: a -> (a, a)
inc2 a
n = let n' :: a
n' = a
n a -> a -> a
forall a. Num a => a -> a -> a
+ a
2 in (a
n', a
n)

getPeerStreamID :: Context -> IO StreamId
getPeerStreamID :: Context -> IO Int
getPeerStreamID Context
ctx = IORef Int -> IO Int
forall a. IORef a -> IO a
readIORef (IORef Int -> IO Int) -> IORef Int -> IO Int
forall a b. (a -> b) -> a -> b
$ Context -> IORef Int
peerStreamId Context
ctx

setPeerStreamID :: Context -> StreamId -> IO ()
setPeerStreamID :: Context -> Int -> IO ()
setPeerStreamID Context
ctx Int
sid =  IORef Int -> Int -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef (Context -> IORef Int
peerStreamId Context
ctx) Int
sid

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

{-# INLINE setStreamState #-}
setStreamState :: Context -> Stream -> StreamState -> IO ()
setStreamState :: Context -> Stream -> StreamState -> IO ()
setStreamState Context
_ Stream{IORef StreamState
streamState :: Stream -> IORef StreamState
streamState :: IORef StreamState
streamState} StreamState
val = IORef StreamState -> StreamState -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef StreamState
streamState StreamState
val

opened :: Context -> Stream -> IO ()
opened :: Context -> Stream -> IO ()
opened ctx :: Context
ctx@Context{IORef Int
concurrency :: IORef Int
concurrency :: Context -> IORef Int
concurrency} Stream
strm = do
    IORef Int -> (Int -> (Int, ())) -> IO ()
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef' IORef Int
concurrency (\Int
x -> (Int
xInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1,()))
    Context -> Stream -> StreamState -> IO ()
setStreamState Context
ctx Stream
strm (OpenState -> StreamState
Open OpenState
JustOpened)

halfClosedRemote :: Context -> Stream -> IO ()
halfClosedRemote :: Context -> Stream -> IO ()
halfClosedRemote Context
ctx stream :: Stream
stream@Stream{IORef StreamState
streamState :: IORef StreamState
streamState :: Stream -> IORef StreamState
streamState} = do
    Maybe ClosedCode
closingCode <- IORef StreamState
-> (StreamState -> (StreamState, Maybe ClosedCode))
-> IO (Maybe ClosedCode)
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef IORef StreamState
streamState StreamState -> (StreamState, Maybe ClosedCode)
closeHalf
    (ClosedCode -> IO ()) -> Maybe ClosedCode -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ (Context -> Stream -> ClosedCode -> IO ()
closed Context
ctx Stream
stream) Maybe ClosedCode
closingCode
  where
    closeHalf :: StreamState -> (StreamState, Maybe ClosedCode)
    closeHalf :: StreamState -> (StreamState, Maybe ClosedCode)
closeHalf x :: StreamState
x@(Closed ClosedCode
_)         = (StreamState
x, Maybe ClosedCode
forall a. Maybe a
Nothing)
    closeHalf (HalfClosedLocal ClosedCode
cc) = (ClosedCode -> StreamState
Closed ClosedCode
cc, ClosedCode -> Maybe ClosedCode
forall a. a -> Maybe a
Just ClosedCode
cc)
    closeHalf StreamState
_                    = (StreamState
HalfClosedRemote, Maybe ClosedCode
forall a. Maybe a
Nothing)

halfClosedLocal :: Context -> Stream -> ClosedCode -> IO ()
halfClosedLocal :: Context -> Stream -> ClosedCode -> IO ()
halfClosedLocal Context
ctx stream :: Stream
stream@Stream{IORef StreamState
streamState :: IORef StreamState
streamState :: Stream -> IORef StreamState
streamState} ClosedCode
cc = do
    Bool
shouldFinalize <- IORef StreamState
-> (StreamState -> (StreamState, Bool)) -> IO Bool
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef IORef StreamState
streamState StreamState -> (StreamState, Bool)
closeHalf
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
shouldFinalize (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
        Context -> Stream -> ClosedCode -> IO ()
closed Context
ctx Stream
stream ClosedCode
cc
  where
    closeHalf :: StreamState -> (StreamState, Bool)
    closeHalf :: StreamState -> (StreamState, Bool)
closeHalf x :: StreamState
x@(Closed ClosedCode
_)     = (StreamState
x, Bool
False)
    closeHalf StreamState
HalfClosedRemote = (ClosedCode -> StreamState
Closed ClosedCode
cc, Bool
True)
    closeHalf StreamState
_                = (ClosedCode -> StreamState
HalfClosedLocal ClosedCode
cc, Bool
False)

closed :: Context -> Stream -> ClosedCode -> IO ()
closed :: Context -> Stream -> ClosedCode -> IO ()
closed ctx :: Context
ctx@Context{IORef Int
concurrency :: IORef Int
concurrency :: Context -> IORef Int
concurrency,StreamTable
streamTable :: StreamTable
streamTable :: Context -> StreamTable
streamTable} strm :: Stream
strm@Stream{Int
streamNumber :: Stream -> Int
streamNumber :: Int
streamNumber} ClosedCode
cc = do
    StreamTable -> Int -> IO ()
remove StreamTable
streamTable Int
streamNumber
    -- TODO: prevent double-counting
    IORef Int -> (Int -> (Int, ())) -> IO ()
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef' IORef Int
concurrency (\Int
x -> (Int
xInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1,()))
    Context -> Stream -> StreamState -> IO ()
setStreamState Context
ctx Stream
strm (ClosedCode -> StreamState
Closed ClosedCode
cc) -- anyway

openStream :: Context -> StreamId -> FrameTypeId -> IO Stream
openStream :: Context -> Int -> FrameTypeId -> IO Stream
openStream ctx :: Context
ctx@Context{StreamTable
streamTable :: StreamTable
streamTable :: Context -> StreamTable
streamTable, IORef Settings
http2settings :: IORef Settings
http2settings :: Context -> IORef Settings
http2settings} Int
sid FrameTypeId
ftyp = do
    Int
ws <- Settings -> Int
initialWindowSize (Settings -> Int) -> IO Settings -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IORef Settings -> IO Settings
forall a. IORef a -> IO a
readIORef IORef Settings
http2settings
    Stream
newstrm <- Int -> Int -> IO Stream
newStream Int
sid (Int -> IO Stream) -> Int -> IO Stream
forall a b. (a -> b) -> a -> b
$ Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ws
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (FrameTypeId
ftyp FrameTypeId -> FrameTypeId -> Bool
forall a. Eq a => a -> a -> Bool
== FrameTypeId
FrameHeaders Bool -> Bool -> Bool
|| FrameTypeId
ftyp FrameTypeId -> FrameTypeId -> Bool
forall a. Eq a => a -> a -> Bool
== FrameTypeId
FramePushPromise) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Context -> Stream -> IO ()
opened Context
ctx Stream
newstrm
    StreamTable -> Int -> Stream -> IO ()
insert StreamTable
streamTable Int
sid Stream
newstrm
    Stream -> IO Stream
forall (m :: * -> *) a. Monad m => a -> m a
return Stream
newstrm