@@ -2,6 +2,7 @@
2{-# LANGUAGE RecordWildCards #-}
2{-# LANGUAGE RecordWildCards #-}
3{-# LANGUAGE BangPatterns #-}
3{-# LANGUAGE BangPatterns #-}
4{-# LANGUAGE CPP #-}
4{-# LANGUAGE CPP #-}
5+{-# LANGUAGE NamedFieldPuns #-}
6module Network.Wai.Handler.Warp.HTTP2.Receiver (frameReceiver) where
7module Network.Wai.Handler.Warp.HTTP2.Receiver (frameReceiver) where
@@ -48,9 +49,9 @@ frameReceiver ctx@Context{..} mkreq recvN =
48 cont <- processStreamGuardingError $ decodeFrameHeader hd
49 cont <- processStreamGuardingError $ decodeFrameHeader hd
49 when cont loop
50 when cont loop
51− processStreamGuardingError (_, FrameHeader{..})
52+ processStreamGuardingError (_, FrameHeader{streamId})
52 | isResponse streamId = E.throwIO $ ConnectionError ProtocolError "stream id should be odd"
53 | isResponse streamId = E.throwIO $ ConnectionError ProtocolError "stream id should be odd"
53− processStreamGuardingError (FrameUnknown _, FrameHeader{..}) = do
54+ processStreamGuardingError (FrameUnknown _, FrameHeader{payloadLength}) = do
54 mx <- readIORef continued
55 mx <- readIORef continued
55 case mx of
56 case mx of
56 Nothing -> do
57 Nothing -> do
@@ -60,7 +61,7 @@ frameReceiver ctx@Context{..} mkreq recvN =
60 Just _ -> E.throwIO $ ConnectionError ProtocolError "unknown frame"
61 Just _ -> E.throwIO $ ConnectionError ProtocolError "unknown frame"
61 processStreamGuardingError (FramePushPromise, _) =
62 processStreamGuardingError (FramePushPromise, _) =
62 E.throwIO $ ConnectionError ProtocolError "push promise is not allowed"
63 E.throwIO $ ConnectionError ProtocolError "push promise is not allowed"
63− processStreamGuardingError typhdr@(ftyp, header@FrameHeader{..}) = do
64+ processStreamGuardingError typhdr@(ftyp, header@FrameHeader{payloadLength}) = do
64 settings <- readIORef http2settings
65 settings <- readIORef http2settings
65 case checkFrameHeader settings typhdr of
66 case checkFrameHeader settings typhdr of
66 Left h2err -> case h2err of
67 Left h2err -> case h2err of
@@ -78,13 +79,13 @@ frameReceiver ctx@Context{..} mkreq recvN =
78 Left connErr -> E.throw connErr
79 Left connErr -> E.throw connErr
79 Right cont -> return cont
80 Right cont -> return cont
81− controlOrStream ftyp header@FrameHeader{..}
82+ controlOrStream ftyp header@FrameHeader{streamId, payloadLength}
82 | isControl streamId = do
83 | isControl streamId = do
83 pl <- recvN payloadLength
84 pl <- recvN payloadLength
84 control ftyp header pl ctx
85 control ftyp header pl ctx
85 | otherwise = do
86 | otherwise = do
86 checkContinued
87 checkContinued
87− strm@Stream{..} <- getStream
88+ strm@Stream{streamState,streamContentLength} <- getStream
88 pl <- recvN payloadLength
89 pl <- recvN payloadLength
89 state <- readIORef streamState
90 state <- readIORef streamState
90 state' <- stream ftyp header pl ctx state strm
91 state' <- stream ftyp header pl ctx state strm
@@ -159,7 +160,7 @@ frameReceiver ctx@Context{..} mkreq recvN =
159----------------------------------------------------------------
160----------------------------------------------------------------
161control :: FrameTypeId -> FrameHeader -> ByteString -> Context -> IO Bool
162control :: FrameTypeId -> FrameHeader -> ByteString -> Context -> IO Bool
162−control FrameSettings header@FrameHeader{..} bs Context{..} = do
163+control FrameSettings header@FrameHeader{flags} bs Context{http2settings, outputQ} = do
163 SettingsFrame alist <- guardIt $ decodeSettingsFrame header bs
164 SettingsFrame alist <- guardIt $ decodeSettingsFrame header bs
164 case checkSettingsList alist of
165 case checkSettingsList alist of
165 Just x -> E.throwIO x
166 Just x -> E.throwIO x
@@ -170,7 +171,7 @@ control FrameSettings header@FrameHeader{..} bs Context{..} = do
170 enqueue outputQ (OFrame frame) highestPriority
171 enqueue outputQ (OFrame frame) highestPriority
171 return True
172 return True
173−control FramePing FrameHeader{..} bs Context{..} =
174+control FramePing FrameHeader{flags} bs Context{outputQ} =
174 if testAck flags then
175 if testAck flags then
175 E.throwIO $ ConnectionError ProtocolError "the ack flag of this ping frame must not be set"
176 E.throwIO $ ConnectionError ProtocolError "the ack flag of this ping frame must not be set"
@@ -178,11 +179,11 @@ control FramePing FrameHeader{..} bs Context{..} =
178 enqueue outputQ (OFrame frame) defaultPriority
179 enqueue outputQ (OFrame frame) defaultPriority
179 return True
180 return True
181−control FrameGoAway _ _ Context{..} = do
182+control FrameGoAway _ _ Context{outputQ} = do
182 enqueue outputQ OFinish highestPriority
183 enqueue outputQ OFinish highestPriority
183 return False
184 return False
185−control FrameWindowUpdate header@FrameHeader{..} bs Context{..} = do
186+control FrameWindowUpdate header bs Context{connectionWindow} = do
186 WindowUpdateFrame n <- guardIt $ decodeWindowUpdateFrame header bs
187 WindowUpdateFrame n <- guardIt $ decodeWindowUpdateFrame header bs
187 w <- (n +) <$> atomically (readTVar connectionWindow)
188 w <- (n +) <$> atomically (readTVar connectionWindow)
188 when (isWindowOverflow w) $ E.throwIO $ ConnectionError FlowControlError "control window should be less than 2^31"
189 when (isWindowOverflow w) $ E.throwIO $ ConnectionError FlowControlError "control window should be less than 2^31"
@@ -208,7 +209,7 @@ checkPriority p me
208 dep = streamDependency p
209 dep = streamDependency p
210stream :: FrameTypeId -> FrameHeader -> ByteString -> Context -> StreamState -> Stream -> IO StreamState
211stream :: FrameTypeId -> FrameHeader -> ByteString -> Context -> StreamState -> Stream -> IO StreamState
211−stream FrameHeaders header@FrameHeader{..} bs ctx (Open JustOpened) Stream{..} = do
212+stream FrameHeaders header@FrameHeader{flags} bs ctx (Open JustOpened) Stream{streamNumber} = do
212 HeadersFrame mp frag <- guardIt $ decodeHeadersFrame header bs
213 HeadersFrame mp frag <- guardIt $ decodeHeadersFrame header bs
213 pri <- case mp of
214 pri <- case mp of
214 Nothing -> return defaultPriority
215 Nothing -> return defaultPriority
@@ -227,7 +228,7 @@ stream FrameHeaders header@FrameHeader{..} bs ctx (Open JustOpened) Stream{..} =
227 let !siz = BS.length frag
228 let !siz = BS.length frag
228 return $ Open $ Continued [frag] siz 1 endOfStream pri
229 return $ Open $ Continued [frag] siz 1 endOfStream pri
230−stream FrameHeaders header@FrameHeader{..} bs _ s@(Open (Body q)) Stream{..} = do
231+stream FrameHeaders header@FrameHeader{flags} bs _ s@(Open (Body q)) _ = do
231 -- trailer is not supported.
232 -- trailer is not supported.
232 -- let's read and ignore it.
233 -- let's read and ignore it.
233 HeadersFrame _ _ <- guardIt $ decodeHeadersFrame header bs
234 HeadersFrame _ _ <- guardIt $ decodeHeadersFrame header bs
@@ -238,7 +239,11 @@ stream FrameHeaders header@FrameHeader{..} bs _ s@(Open (Body q)) Stream{..} = d
241−stream FrameData header@FrameHeader{..} bs Context{..} s@(Open (Body q)) Stream{..} = do
242+stream FrameData
243+ header@FrameHeader{flags,payloadLength,streamId}
245+ Context{outputQ} s@(Open (Body q))
246+ Stream{streamNumber,streamBodyLength,streamContentLength} = do
242 DataFrame body <- guardIt $ decodeDataFrame header bs
247 DataFrame body <- guardIt $ decodeDataFrame header bs
243 let endOfStream = testEndStream flags
248 let endOfStream = testEndStream flags
244 len0 <- readIORef streamBodyLength
249 len0 <- readIORef streamBodyLength
@@ -260,7 +265,7 @@ stream FrameData header@FrameHeader{..} bs Context{..} s@(Open (Body q)) Stream{
263−stream FrameContinuation FrameHeader{..} frag ctx (Open (Continued rfrags siz n endOfStream pri)) _ = do
268+stream FrameContinuation FrameHeader{flags} frag ctx (Open (Continued rfrags siz n endOfStream pri)) _ = do
264 let endOfHeader = testEndHeader flags
269 let endOfHeader = testEndHeader flags
265 rfrags' = frag : rfrags
270 rfrags' = frag : rfrags
266 siz' = siz + BS.length frag
271 siz' = siz + BS.length frag
@@ -281,7 +286,7 @@ stream FrameContinuation FrameHeader{..} frag ctx (Open (Continued rfrags siz n
282stream FrameContinuation _ _ _ _ _ = E.throwIO $ ConnectionError ProtocolError "continue frame cannot come here"
287stream FrameContinuation _ _ _ _ _ = E.throwIO $ ConnectionError ProtocolError "continue frame cannot come here"
284−stream FrameWindowUpdate header@FrameHeader{..} bs Context{..} s Stream{..} = do
289+stream FrameWindowUpdate header@FrameHeader{streamId} bs _ s Stream{streamWindow} = do
285 WindowUpdateFrame n <- guardIt $ decodeWindowUpdateFrame header bs
290 WindowUpdateFrame n <- guardIt $ decodeWindowUpdateFrame header bs
286 w <- (n +) <$> atomically (readTVar streamWindow)
291 w <- (n +) <$> atomically (readTVar streamWindow)
287 when (isWindowOverflow w) $
292 when (isWindowOverflow w) $
@@ -295,7 +300,7 @@ stream FrameRSTStream header bs ctx _ strm = do
295 closed ctx strm cc
300 closed ctx strm cc
296 return $ Closed cc -- will be written to streamState again
301 return $ Closed cc -- will be written to streamState again
298−stream FramePriority header bs Context{..} s Stream{..} = do
303+stream FramePriority header bs Context{outputQ} s Stream{streamNumber} = do
299 PriorityFrame p <- guardIt $ decodePriorityFrame header bs
304 PriorityFrame p <- guardIt $ decodePriorityFrame header bs
300 checkPriority p streamNumber
305 checkPriority p streamNumber
301 prepare outputQ streamNumber p
306 prepare outputQ streamNumber p
@@ -303,5 +308,5 @@ stream FramePriority header bs Context{..} s Stream{..} = do
304-- this ordering is important
309-- this ordering is important
305stream _ _ _ _ (Open Continued{}) _ = E.throwIO $ ConnectionError ProtocolError "an illegal frame follows header/continuation frames"
310stream _ _ _ _ (Open Continued{}) _ = E.throwIO $ ConnectionError ProtocolError "an illegal frame follows header/continuation frames"
306−stream FrameData FrameHeader{..} _ _ _ _ = E.throwIO $ StreamError StreamClosed streamId
311+stream FrameData FrameHeader{streamId} _ _ _ _ = E.throwIO $ StreamError StreamClosed streamId
307−stream _ FrameHeader{..} _ _ _ _ = E.throwIO $ StreamError ProtocolError streamId
312+stream _ FrameHeader{streamId} _ _ _ _ = E.throwIO $ StreamError ProtocolError streamId