{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecordWildCards #-}

module Network.HTTP2.Client.Run where

import Control.Concurrent.STM (check)
import Control.Exception
import UnliftIO.Async
import UnliftIO.Concurrent
import UnliftIO.STM

import Imports
import Network.HTTP2.Arch
import Network.HTTP2.Client.Types
import Network.HTTP2.Frame
import Data.ByteString.Builder (Builder)

-- | Client configuration
data ClientConfig = ClientConfig {
    ClientConfig -> Scheme
scheme     :: Scheme    -- ^ https or http
  , ClientConfig -> Scheme
authority  :: Authority -- ^ Server name
  , ClientConfig -> StreamId
cacheLimit :: Int       -- ^ How many pushed responses are contained in the cache
  }

-- | Running HTTP/2 client.
run :: ClientConfig -> Config -> Client a -> IO a
run :: forall a. ClientConfig -> Config -> Client a -> IO a
run ClientConfig{StreamId
Scheme
scheme :: ClientConfig -> Scheme
authority :: ClientConfig -> Scheme
cacheLimit :: ClientConfig -> StreamId
scheme :: Scheme
authority :: Scheme
cacheLimit :: StreamId
..} conf :: Config
conf@Config{StreamId
Buffer
Manager
SockAddr
StreamId -> IO Scheme
PositionReadMaker
Scheme -> IO ()
confWriteBuffer :: Buffer
confBufferSize :: StreamId
confSendAll :: Scheme -> IO ()
confReadN :: StreamId -> IO Scheme
confPositionReadMaker :: PositionReadMaker
confTimeoutManager :: Manager
confMySockAddr :: SockAddr
confPeerSockAddr :: SockAddr
confWriteBuffer :: Config -> Buffer
confBufferSize :: Config -> StreamId
confSendAll :: Config -> Scheme -> IO ()
confReadN :: Config -> StreamId -> IO Scheme
confPositionReadMaker :: Config -> PositionReadMaker
confTimeoutManager :: Config -> Manager
confMySockAddr :: Config -> SockAddr
confPeerSockAddr :: Config -> SockAddr
..} Client a
client = do
    RoleInfo
clientInfo <- Scheme -> Scheme -> StreamId -> IO RoleInfo
newClientInfo Scheme
scheme Scheme
authority StreamId
cacheLimit
    Context
ctx <- RoleInfo -> StreamId -> SockAddr -> SockAddr -> IO Context
newContext RoleInfo
clientInfo StreamId
confBufferSize SockAddr
confMySockAddr SockAddr
confPeerSockAddr
    Manager
mgr <- Manager -> IO Manager
start Manager
confTimeoutManager
    let runBackgroundThreads :: IO ()
runBackgroundThreads = do
            let runReceiver :: IO ()
runReceiver = Context -> Config -> IO ()
frameReceiver Context
ctx Config
conf
                runSender :: IO ()
runSender   = Context -> Config -> Manager -> IO ()
frameSender   Context
ctx Config
conf Manager
mgr
            IO () -> IO () -> IO ()
forall (m :: * -> *) a b. MonadUnliftIO m => m a -> m b -> m ()
concurrently_ IO ()
runReceiver IO ()
runSender
    Config -> Context -> IO ()
exchangeSettings Config
conf Context
ctx
    MVar ()
mvar <- () -> IO (MVar ())
forall (m :: * -> *) a. MonadIO m => a -> m (MVar a)
newMVar ()
    let runClient :: IO a
runClient = do
            a
x <- Client a
client Client a -> Client a
forall a b. (a -> b) -> a -> b
$ Context
-> Manager
-> Scheme
-> Scheme
-> Request
-> (Response -> IO b)
-> IO b
forall a.
Context
-> Manager
-> Scheme
-> Scheme
-> Request
-> (Response -> IO a)
-> IO a
sendRequest Context
ctx Manager
mgr Scheme
scheme Scheme
authority
            Manager -> IO ()
waitCounter0 Manager
mgr
            let frame :: Scheme
frame = StreamId -> ErrorCode -> Scheme -> Scheme
goawayFrame StreamId
0 ErrorCode
NoError Scheme
"graceful closing"
            TQueue Control -> Control -> IO ()
enqueueControl (Context -> TQueue Control
controlQ Context
ctx) (Control -> IO ()) -> Control -> IO ()
forall a b. (a -> b) -> a -> b
$ Scheme -> MVar () -> Control
CGoaway Scheme
frame MVar ()
mvar
            MVar () -> IO ()
forall (m :: * -> *) a. MonadIO m => MVar a -> m a
takeMVar MVar ()
mvar
            a -> IO a
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
x
    Manager
-> IO (Either () a)
-> (Either SomeException (Either () a) -> IO a)
-> IO a
forall a b.
Manager -> IO a -> (Either SomeException a -> IO b) -> IO b
stopAfter Manager
mgr (IO () -> IO a -> IO (Either () a)
forall (m :: * -> *) a b.
MonadUnliftIO m =>
m a -> m b -> m (Either a b)
race IO ()
runBackgroundThreads IO a
runClient) ((Either SomeException (Either () a) -> IO a) -> IO a)
-> (Either SomeException (Either () a) -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Either SomeException (Either () a)
res -> do
      StreamTable -> Maybe SomeException -> IO ()
closeAllStreams (Context -> StreamTable
streamTable Context
ctx) (Maybe SomeException -> IO ()) -> Maybe SomeException -> IO ()
forall a b. (a -> b) -> a -> b
$ (SomeException -> Maybe SomeException)
-> (Either () a -> Maybe SomeException)
-> Either SomeException (Either () a)
-> Maybe SomeException
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either SomeException -> Maybe SomeException
forall a. a -> Maybe a
Just (Maybe SomeException -> Either () a -> Maybe SomeException
forall a b. a -> b -> a
const Maybe SomeException
forall a. Maybe a
Nothing) Either SomeException (Either () a)
res
      case Either SomeException (Either () a)
res of
        Left SomeException
err ->
          SomeException -> IO a
forall e a. Exception e => e -> IO a
throwIO SomeException
err
        Right (Left ()) ->
          IO a
forall a. HasCallStack => a
undefined -- never reach
        Right (Right a
x) ->
          a -> IO a
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
x

sendRequest :: Context -> Manager -> Scheme -> Authority -> Request -> (Response -> IO a) -> IO a
sendRequest :: forall a.
Context
-> Manager
-> Scheme
-> Scheme
-> Request
-> (Response -> IO a)
-> IO a
sendRequest ctx :: Context
ctx@Context{IORef Bool
IORef StreamId
IORef (Maybe StreamId)
IORef (Maybe SettingsList)
IORef Settings
DynamicTable
TVar StreamId
TQueue Control
TQueue (Output Stream)
Rate
SockAddr
StreamTable
RoleInfo
Role
controlQ :: Context -> TQueue Control
streamTable :: Context -> StreamTable
role :: Role
roleInfo :: RoleInfo
myFirstSettings :: IORef Bool
myPendingAlist :: IORef (Maybe SettingsList)
mySettings :: IORef Settings
peerSettings :: IORef Settings
streamTable :: StreamTable
concurrency :: IORef StreamId
continued :: IORef (Maybe StreamId)
myStreamId :: IORef StreamId
peerStreamId :: IORef StreamId
outputBufferLimit :: IORef StreamId
outputQ :: TQueue (Output Stream)
outputQStreamID :: TVar StreamId
controlQ :: TQueue Control
encodeDynamicTable :: DynamicTable
decodeDynamicTable :: DynamicTable
txConnectionWindow :: TVar StreamId
rxConnectionInc :: IORef StreamId
pingRate :: Rate
settingsRate :: Rate
emptyFrameRate :: Rate
rstRate :: Rate
mySockAddr :: SockAddr
peerSockAddr :: SockAddr
role :: Context -> Role
roleInfo :: Context -> RoleInfo
myFirstSettings :: Context -> IORef Bool
myPendingAlist :: Context -> IORef (Maybe SettingsList)
mySettings :: Context -> IORef Settings
peerSettings :: Context -> IORef Settings
concurrency :: Context -> IORef StreamId
continued :: Context -> IORef (Maybe StreamId)
myStreamId :: Context -> IORef StreamId
peerStreamId :: Context -> IORef StreamId
outputBufferLimit :: Context -> IORef StreamId
outputQ :: Context -> TQueue (Output Stream)
outputQStreamID :: Context -> TVar StreamId
encodeDynamicTable :: Context -> DynamicTable
decodeDynamicTable :: Context -> DynamicTable
txConnectionWindow :: Context -> TVar StreamId
rxConnectionInc :: Context -> IORef StreamId
pingRate :: Context -> Rate
settingsRate :: Context -> Rate
emptyFrameRate :: Context -> Rate
rstRate :: Context -> Rate
mySockAddr :: Context -> SockAddr
peerSockAddr :: Context -> SockAddr
..} Manager
mgr Scheme
scheme Scheme
auth (Request OutObj
req) Response -> IO a
processResponse = do
    -- Checking push promises
    let hdr0 :: [Header]
hdr0 = OutObj -> [Header]
outObjHeaders OutObj
req
        method :: Scheme
method = Scheme -> Maybe Scheme -> Scheme
forall a. a -> Maybe a -> a
fromMaybe ([Char] -> Scheme
forall a. HasCallStack => [Char] -> a
error [Char]
"sendRequest:method") (Maybe Scheme -> Scheme) -> Maybe Scheme -> Scheme
forall a b. (a -> b) -> a -> b
$ HeaderName -> [Header] -> Maybe Scheme
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup HeaderName
":method" [Header]
hdr0
        path :: Scheme
path   = Scheme -> Maybe Scheme -> Scheme
forall a. a -> Maybe a -> a
fromMaybe ([Char] -> Scheme
forall a. HasCallStack => [Char] -> a
error [Char]
"sendRequest:path") (Maybe Scheme -> Scheme) -> Maybe Scheme -> Scheme
forall a b. (a -> b) -> a -> b
$ HeaderName -> [Header] -> Maybe Scheme
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup HeaderName
":path" [Header]
hdr0
    Maybe Stream
mstrm0 <- Scheme -> Scheme -> RoleInfo -> IO (Maybe Stream)
lookupCache Scheme
method Scheme
path RoleInfo
roleInfo
    Stream
strm <- case Maybe Stream
mstrm0 of
      Maybe Stream
Nothing -> do
          -- Arch/Sender is originally implemented for servers where
          -- the ordering of responses can be out-of-order.
          -- But for clients, the ordering must be maintained.
          -- To implement this, 'outputQStreamID' is used.
          -- Also, for 'OutBodyStreaming', TBQ must not be empty
          -- when its 'Output' is enqueued into 'outputQ'.
          -- Otherwise, it would be re-enqueue because of empty
          -- resulting in out-of-order.
          -- To implement this, 'tbqNonEmpty' is used.
          let hdr1 :: [Header]
hdr1 | Scheme
scheme Scheme -> Scheme -> Bool
forall a. Eq a => a -> a -> Bool
/= Scheme
"" = (HeaderName
":scheme", Scheme
scheme) Header -> [Header] -> [Header]
forall a. a -> [a] -> [a]
: [Header]
hdr0
                   | Bool
otherwise    = [Header]
hdr0
              hdr2 :: [Header]
hdr2 | Scheme
auth Scheme -> Scheme -> Bool
forall a. Eq a => a -> a -> Bool
/= Scheme
"" = (HeaderName
":authority", Scheme
auth) Header -> [Header] -> [Header]
forall a. a -> [a] -> [a]
: [Header]
hdr1
                   | Bool
otherwise  = [Header]
hdr1
              req' :: OutObj
req' = OutObj
req { outObjHeaders = hdr2 }
          StreamId
sid <- Context -> IO StreamId
getMyNewStreamId Context
ctx
          Stream
newstrm <- Context -> StreamId -> FrameType -> IO Stream
openStream Context
ctx StreamId
sid FrameType
FrameHeaders
          case OutObj -> OutBody
outObjBody OutObj
req of
            OutBodyStreaming (Builder -> IO ()) -> IO () -> IO ()
strmbdy ->
                Context
-> Manager
-> OutObj
-> StreamId
-> Stream
-> ((forall x. IO x -> IO x)
    -> (Builder -> IO ()) -> IO () -> IO ())
-> IO ()
sendStreaming Context
ctx Manager
mgr OutObj
req' StreamId
sid Stream
newstrm (((forall x. IO x -> IO x) -> (Builder -> IO ()) -> IO () -> IO ())
 -> IO ())
-> ((forall x. IO x -> IO x)
    -> (Builder -> IO ()) -> IO () -> IO ())
-> IO ()
forall a b. (a -> b) -> a -> b
$ \forall x. IO x -> IO x
unmask Builder -> IO ()
push IO ()
flush ->
                    IO () -> IO ()
forall x. IO x -> IO x
unmask (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ (Builder -> IO ()) -> IO () -> IO ()
strmbdy Builder -> IO ()
push IO ()
flush
            OutBodyStreamingUnmask (forall x. IO x -> IO x) -> (Builder -> IO ()) -> IO () -> IO ()
strmbdy ->
                Context
-> Manager
-> OutObj
-> StreamId
-> Stream
-> ((forall x. IO x -> IO x)
    -> (Builder -> IO ()) -> IO () -> IO ())
-> IO ()
sendStreaming Context
ctx Manager
mgr OutObj
req' StreamId
sid Stream
newstrm (forall x. IO x -> IO x) -> (Builder -> IO ()) -> IO () -> IO ()
strmbdy
            OutBody
_ -> STM () -> IO ()
forall (m :: * -> *) a. MonadIO m => STM a -> m a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
                StreamId
sidOK <- TVar StreamId -> STM StreamId
forall a. TVar a -> STM a
readTVar TVar StreamId
outputQStreamID
                Bool -> STM ()
check (StreamId
sidOK StreamId -> StreamId -> Bool
forall a. Eq a => a -> a -> Bool
== StreamId
sid)
                TVar StreamId -> StreamId -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar StreamId
outputQStreamID (StreamId
sid StreamId -> StreamId -> StreamId
forall a. Num a => a -> a -> a
+ StreamId
2)
                TQueue (Output Stream) -> Output Stream -> STM ()
forall a. TQueue a -> a -> STM ()
writeTQueue TQueue (Output Stream)
outputQ (Output Stream -> STM ()) -> Output Stream -> STM ()
forall a b. (a -> b) -> a -> b
$ Stream
-> OutObj
-> OutputType
-> Maybe (TBQueue StreamingChunk)
-> IO ()
-> Output Stream
forall a.
a
-> OutObj
-> OutputType
-> Maybe (TBQueue StreamingChunk)
-> IO ()
-> Output a
Output Stream
newstrm OutObj
req' OutputType
OObj Maybe (TBQueue StreamingChunk)
forall a. Maybe a
Nothing (() -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ())
          Stream -> IO Stream
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Stream
newstrm
      Just Stream
strm0 -> Stream -> IO Stream
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Stream
strm0
    InpObj
rsp <- MVar InpObj -> IO InpObj
forall (m :: * -> *) a. MonadIO m => MVar a -> m a
takeMVar (MVar InpObj -> IO InpObj) -> MVar InpObj -> IO InpObj
forall a b. (a -> b) -> a -> b
$ Stream -> MVar InpObj
streamInput Stream
strm
    Response -> IO a
processResponse (Response -> IO a) -> Response -> IO a
forall a b. (a -> b) -> a -> b
$ InpObj -> Response
Response InpObj
rsp

sendStreaming :: Context -> Manager -> OutObj -> StreamId -> Stream
              -> ((forall x. IO x -> IO x) -> (Builder -> IO ()) -> IO () -> IO ())
              -> IO ()
sendStreaming :: Context
-> Manager
-> OutObj
-> StreamId
-> Stream
-> ((forall x. IO x -> IO x)
    -> (Builder -> IO ()) -> IO () -> IO ())
-> IO ()
sendStreaming Context{IORef Bool
IORef StreamId
IORef (Maybe StreamId)
IORef (Maybe SettingsList)
IORef Settings
DynamicTable
TVar StreamId
TQueue Control
TQueue (Output Stream)
Rate
SockAddr
StreamTable
RoleInfo
Role
controlQ :: Context -> TQueue Control
streamTable :: Context -> StreamTable
role :: Context -> Role
roleInfo :: Context -> RoleInfo
myFirstSettings :: Context -> IORef Bool
myPendingAlist :: Context -> IORef (Maybe SettingsList)
mySettings :: Context -> IORef Settings
peerSettings :: Context -> IORef Settings
concurrency :: Context -> IORef StreamId
continued :: Context -> IORef (Maybe StreamId)
myStreamId :: Context -> IORef StreamId
peerStreamId :: Context -> IORef StreamId
outputBufferLimit :: Context -> IORef StreamId
outputQ :: Context -> TQueue (Output Stream)
outputQStreamID :: Context -> TVar StreamId
encodeDynamicTable :: Context -> DynamicTable
decodeDynamicTable :: Context -> DynamicTable
txConnectionWindow :: Context -> TVar StreamId
rxConnectionInc :: Context -> IORef StreamId
pingRate :: Context -> Rate
settingsRate :: Context -> Rate
emptyFrameRate :: Context -> Rate
rstRate :: Context -> Rate
mySockAddr :: Context -> SockAddr
peerSockAddr :: Context -> SockAddr
role :: Role
roleInfo :: RoleInfo
myFirstSettings :: IORef Bool
myPendingAlist :: IORef (Maybe SettingsList)
mySettings :: IORef Settings
peerSettings :: IORef Settings
streamTable :: StreamTable
concurrency :: IORef StreamId
continued :: IORef (Maybe StreamId)
myStreamId :: IORef StreamId
peerStreamId :: IORef StreamId
outputBufferLimit :: IORef StreamId
outputQ :: TQueue (Output Stream)
outputQStreamID :: TVar StreamId
controlQ :: TQueue Control
encodeDynamicTable :: DynamicTable
decodeDynamicTable :: DynamicTable
txConnectionWindow :: TVar StreamId
rxConnectionInc :: IORef StreamId
pingRate :: Rate
settingsRate :: Rate
emptyFrameRate :: Rate
rstRate :: Rate
mySockAddr :: SockAddr
peerSockAddr :: SockAddr
..} Manager
mgr OutObj
req StreamId
sid Stream
newstrm (forall x. IO x -> IO x) -> (Builder -> IO ()) -> IO () -> IO ()
strmbdy = do
    TBQueue StreamingChunk
tbq <- Natural -> IO (TBQueue StreamingChunk)
forall (m :: * -> *) a. MonadIO m => Natural -> m (TBQueue a)
newTBQueueIO Natural
10 -- fixme: hard coding: 10
    TVar Bool
tbqNonEmpty <- Bool -> IO (TVar Bool)
forall (m :: * -> *) a. MonadIO m => a -> m (TVar a)
newTVarIO Bool
False
    Manager -> ((forall x. IO x -> IO x) -> IO ()) -> IO ()
forkManagedUnmask Manager
mgr (((forall x. IO x -> IO x) -> IO ()) -> IO ())
-> ((forall x. IO x -> IO x) -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \forall x. IO x -> IO x
unmask -> do
        let push :: Builder -> m ()
push Builder
b = STM () -> m ()
forall (m :: * -> *) a. MonadIO m => STM a -> m a
atomically (STM () -> m ()) -> STM () -> m ()
forall a b. (a -> b) -> a -> b
$ do
                TBQueue StreamingChunk -> StreamingChunk -> STM ()
forall a. TBQueue a -> a -> STM ()
writeTBQueue TBQueue StreamingChunk
tbq (Builder -> StreamingChunk
StreamingBuilder Builder
b)
                TVar Bool -> Bool -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar Bool
tbqNonEmpty Bool
True
            flush :: IO ()
flush  = STM () -> IO ()
forall (m :: * -> *) a. MonadIO m => STM a -> m a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ TBQueue StreamingChunk -> StreamingChunk -> STM ()
forall a. TBQueue a -> a -> STM ()
writeTBQueue TBQueue StreamingChunk
tbq StreamingChunk
StreamingFlush
            finished :: IO ()
finished = STM () -> IO ()
forall (m :: * -> *) a. MonadIO m => STM a -> m a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ TBQueue StreamingChunk -> StreamingChunk -> STM ()
forall a. TBQueue a -> a -> STM ()
writeTBQueue TBQueue StreamingChunk
tbq (StreamingChunk -> STM ()) -> StreamingChunk -> STM ()
forall a b. (a -> b) -> a -> b
$ IO () -> StreamingChunk
StreamingFinished (Manager -> IO ()
decCounter Manager
mgr)
        Manager -> IO ()
incCounter Manager
mgr
        (forall x. IO x -> IO x) -> (Builder -> IO ()) -> IO () -> IO ()
strmbdy IO x -> IO x
forall x. IO x -> IO x
unmask Builder -> IO ()
forall {m :: * -> *}. MonadIO m => Builder -> m ()
push IO ()
flush IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO a
`finally` IO ()
finished
    STM () -> IO ()
forall (m :: * -> *) a. MonadIO m => STM a -> m a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
        StreamId
sidOK <- TVar StreamId -> STM StreamId
forall a. TVar a -> STM a
readTVar TVar StreamId
outputQStreamID
        Bool
ready <- TVar Bool -> STM Bool
forall a. TVar a -> STM a
readTVar TVar Bool
tbqNonEmpty
        Bool -> STM ()
check (StreamId
sidOK StreamId -> StreamId -> Bool
forall a. Eq a => a -> a -> Bool
== StreamId
sid Bool -> Bool -> Bool
&& Bool
ready)
        TVar StreamId -> StreamId -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar StreamId
outputQStreamID (StreamId
sid StreamId -> StreamId -> StreamId
forall a. Num a => a -> a -> a
+ StreamId
2)
        TQueue (Output Stream) -> Output Stream -> STM ()
forall a. TQueue a -> a -> STM ()
writeTQueue TQueue (Output Stream)
outputQ (Output Stream -> STM ()) -> Output Stream -> STM ()
forall a b. (a -> b) -> a -> b
$ Stream
-> OutObj
-> OutputType
-> Maybe (TBQueue StreamingChunk)
-> IO ()
-> Output Stream
forall a.
a
-> OutObj
-> OutputType
-> Maybe (TBQueue StreamingChunk)
-> IO ()
-> Output a
Output Stream
newstrm OutObj
req OutputType
OObj (TBQueue StreamingChunk -> Maybe (TBQueue StreamingChunk)
forall a. a -> Maybe a
Just TBQueue StreamingChunk
tbq) (() -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ())

exchangeSettings :: Config -> Context -> IO ()
exchangeSettings :: Config -> Context -> IO ()
exchangeSettings Config
conf ctx :: Context
ctx@Context{IORef Bool
IORef StreamId
IORef (Maybe StreamId)
IORef (Maybe SettingsList)
IORef Settings
DynamicTable
TVar StreamId
TQueue Control
TQueue (Output Stream)
Rate
SockAddr
StreamTable
RoleInfo
Role
controlQ :: Context -> TQueue Control
streamTable :: Context -> StreamTable
role :: Context -> Role
roleInfo :: Context -> RoleInfo
myFirstSettings :: Context -> IORef Bool
myPendingAlist :: Context -> IORef (Maybe SettingsList)
mySettings :: Context -> IORef Settings
peerSettings :: Context -> IORef Settings
concurrency :: Context -> IORef StreamId
continued :: Context -> IORef (Maybe StreamId)
myStreamId :: Context -> IORef StreamId
peerStreamId :: Context -> IORef StreamId
outputBufferLimit :: Context -> IORef StreamId
outputQ :: Context -> TQueue (Output Stream)
outputQStreamID :: Context -> TVar StreamId
encodeDynamicTable :: Context -> DynamicTable
decodeDynamicTable :: Context -> DynamicTable
txConnectionWindow :: Context -> TVar StreamId
rxConnectionInc :: Context -> IORef StreamId
pingRate :: Context -> Rate
settingsRate :: Context -> Rate
emptyFrameRate :: Context -> Rate
rstRate :: Context -> Rate
mySockAddr :: Context -> SockAddr
peerSockAddr :: Context -> SockAddr
role :: Role
roleInfo :: RoleInfo
myFirstSettings :: IORef Bool
myPendingAlist :: IORef (Maybe SettingsList)
mySettings :: IORef Settings
peerSettings :: IORef Settings
streamTable :: StreamTable
concurrency :: IORef StreamId
continued :: IORef (Maybe StreamId)
myStreamId :: IORef StreamId
peerStreamId :: IORef StreamId
outputBufferLimit :: IORef StreamId
outputQ :: TQueue (Output Stream)
outputQStreamID :: TVar StreamId
controlQ :: TQueue Control
encodeDynamicTable :: DynamicTable
decodeDynamicTable :: DynamicTable
txConnectionWindow :: TVar StreamId
rxConnectionInc :: IORef StreamId
pingRate :: Rate
settingsRate :: Rate
emptyFrameRate :: Rate
rstRate :: Rate
mySockAddr :: SockAddr
peerSockAddr :: SockAddr
..} = do
    [Scheme]
frames <- Config -> Context -> IO [Scheme]
updateMySettings Config
conf Context
ctx
    let setframe :: Control
setframe = Maybe SettingsList -> [Scheme] -> Control
CFrames Maybe SettingsList
forall a. Maybe a
Nothing (Scheme
connectionPrefaceScheme -> [Scheme] -> [Scheme]
forall a. a -> [a] -> [a]
:[Scheme]
frames)
    TQueue Control -> Control -> IO ()
enqueueControl TQueue Control
controlQ Control
setframe