on master help sign in
concatenating initial HTTP/2 settings.
fb850ffKazu Yamamoto
warp/Network/Wai/Handler/Warp/HTTP2.hs−4
@@ -22,16 +22,12 @@ import Network.Wai.Handler.Warp.Types
22
22
23----------------------------------------------------------------
23----------------------------------------------------------------
24
24
25−initialFrame :: ByteString
26−initialFrame = settingsFrame id [(SettingsMaxConcurrentStreams,recommendedConcurrency)]
27−
28http2 :: Connection -> InternalInfo -> SockAddr -> Transport -> S.Settings -> (BufSize -> IO ByteString) -> Application -> IO ()
25http2 :: Connection -> InternalInfo -> SockAddr -> Transport -> S.Settings -> (BufSize -> IO ByteString) -> Application -> IO ()
29http2 conn ii addr transport settings readN app = do
26http2 conn ii addr transport settings readN app = do
30 checkTLS
27 checkTLS
31 ok <- checkPreface
28 ok <- checkPreface
32 when ok $ do
29 when ok $ do
33 ctx <- newContext
30 ctx <- newContext
34− enqueueOutputControl (outputQ ctx) $ OFrame initialFrame
35 -- Workers, worker manager and timer manager
31 -- Workers, worker manager and timer manager
36 mgr <- start settings
32 mgr <- start settings
37 let responder = response ii settings ctx mgr
33 let responder = response ii settings ctx mgr
warp/Network/Wai/Handler/Warp/HTTP2/Receiver.hs+8−2
@@ -172,10 +172,13 @@ frameReceiver ctx mkreq recvN = loop 0 `E.catch` sendGoaway
172
172
173 consume = void . recvN
173 consume = void . recvN
174
174
175+initialFrame :: ByteString
176+initialFrame = settingsFrame id [(SettingsMaxConcurrentStreams,recommendedConcurrency)]
177+
175----------------------------------------------------------------
178----------------------------------------------------------------
176
179
177control :: FrameTypeId -> FrameHeader -> ByteString -> Context -> IO Bool
180control :: FrameTypeId -> FrameHeader -> ByteString -> Context -> IO Bool
178−control FrameSettings header@FrameHeader{flags} bs Context{http2settings, outputQ} = do
181+control FrameSettings header@FrameHeader{flags} bs Context{http2settings, outputQ,firstSettings} = do
179 SettingsFrame alist <- guardIt $ decodeSettingsFrame header bs
182 SettingsFrame alist <- guardIt $ decodeSettingsFrame header bs
180 case checkSettingsList alist of
183 case checkSettingsList alist of
181 Just x -> E.throwIO x
184 Just x -> E.throwIO x
@@ -183,7 +186,10 @@ control FrameSettings header@FrameHeader{flags} bs Context{http2settings, output
183 unless (testAck flags) $ do
186 unless (testAck flags) $ do
184 modifyIORef' http2settings $ \old -> updateSettings old alist
187 modifyIORef' http2settings $ \old -> updateSettings old alist
185 let !frame = settingsFrame setAck []
188 let !frame = settingsFrame setAck []
189+ sent <- readIORef firstSettings
190+ let !frame' = if sent then frame else BS.append initialFrame frame
191+ unless sent $ writeIORef firstSettings True
186− enqueueOutputControl outputQ $ OSettings frame alist
192+ enqueueOutputControl outputQ $ OSettings frame' alist
187 return True
193 return True
188
194
189control FramePing FrameHeader{flags} bs Context{outputQ} =
195control FramePing FrameHeader{flags} bs Context{outputQ} =
warp/Network/Wai/Handler/Warp/HTTP2/Types.hs+2
@@ -75,6 +75,7 @@ data BodyInfo = OneshotWithBody
75-- | The context for HTTP/2 connection.
75-- | The context for HTTP/2 connection.
76data Context = Context {
76data Context = Context {
77 http2settings :: !(IORef Settings)
77 http2settings :: !(IORef Settings)
78+ , firstSettings :: !(IORef Bool)
78 , streamTable :: !StreamTable
79 , streamTable :: !StreamTable
79 , concurrency :: !(IORef Int)
80 , concurrency :: !(IORef Int)
80 , priorityTreeSize :: !(IORef Int)
81 , priorityTreeSize :: !(IORef Int)
@@ -95,6 +96,7 @@ data Context = Context {
95
96
96newContext :: IO Context
97newContext :: IO Context
97newContext = Context <$> newIORef defaultSettings
98newContext = Context <$> newIORef defaultSettings
99+ <*> newIORef False
98 <*> newStreamTable
100 <*> newStreamTable
99 <*> newIORef 0
101 <*> newIORef 0
100 <*> newIORef 0
102 <*> newIORef 0