@@ -15,26 +15,14 @@ import qualified Data.ByteString.Builder.Extra as B
15import Foreign.Ptr
15import Foreign.Ptr
16import Network.HTTP2
16import Network.HTTP2
17import Network.HTTP2.Priority
17import Network.HTTP2.Priority
18−import Network.Wai hiding (Response)
18+import Network.Wai.HTTP2 (Trailers)
19−import Network.Wai.HTTP2 (Trailers, Response(..))
20import Network.Wai.Handler.Warp.Buffer
19import Network.Wai.Handler.Warp.Buffer
21import Network.Wai.Handler.Warp.HTTP2.EncodeFrame
20import Network.Wai.Handler.Warp.HTTP2.EncodeFrame
22import Network.Wai.Handler.Warp.HTTP2.HPACK
21import Network.Wai.Handler.Warp.HTTP2.HPACK
23import Network.Wai.Handler.Warp.HTTP2.Types
22import Network.Wai.Handler.Warp.HTTP2.Types
24import Network.Wai.Handler.Warp.IORef
23import Network.Wai.Handler.Warp.IORef
25import qualified Network.Wai.Handler.Warp.Settings as S
24import qualified Network.Wai.Handler.Warp.Settings as S
26−import qualified Network.Wai.Handler.Warp.Timeout as T
27import Network.Wai.Handler.Warp.Types
25import Network.Wai.Handler.Warp.Types
28−import qualified System.PosixCompat.Files as P
31−import qualified System.IO as IO
33−import Network.Wai.Handler.Warp.FdCache
34−import Network.Wai.Handler.Warp.SendFile (positionRead)
35−import System.Posix.IO (openFd, OpenFileFlags(..), defaultFileFlags, OpenMode(ReadOnly), closeFd)
36−import System.Posix.Types
39----------------------------------------------------------------
27----------------------------------------------------------------
@@ -98,27 +86,10 @@ frameSender ctx@Context{outputQ,connectionWindow}
98 lim <- getWindowSize connectionWindow (streamWindow strm)
86 lim <- getWindowSize connectionWindow (streamWindow strm)
99 -- Header frame and Continuation frame
87 -- Header frame and Continuation frame
100 let sid = streamNumber strm
88 let sid = streamNumber strm
101− endOfStream = case aux of
103− Oneshot hb -> not hb
104 builder <- hpackEncodeHeader ctx ii settings rsp
89 builder <- hpackEncodeHeader ctx ii settings rsp
105− len <- headerContinue sid builder endOfStream
90+ len <- headerContinue sid builder False
106 let total = len + frameHeaderLength
91 let total = len + frameHeaderLength
107 case aux of
92 case aux of
108− Oneshot True -> do -- hasBody
109− -- Data frame payload
110− (off, _) <- sendHeadersIfNecessary total
111− let payloadOff = off + frameHeaderLength
112− Next datPayloadLen mnext <-
113− fillResponseBodyGetNext conn ii payloadOff lim rsp
114− fillDataHeaderSend strm total datPayloadLen mnext
115− maybeEnqueueNext strm mnext
117− -- "closed" must be before "connSendAll". If not,
118− -- the context would be switched to the receiver,
119− -- resulting the inconsistency of concurrency.
120− closed ctx strm Finished
122 Persist sq tvar -> do
93 Persist sq tvar -> do
123 (off, needSend) <- sendHeadersIfNecessary total
94 (off, needSend) <- sendHeadersIfNecessary total
124 let payloadOff = off + frameHeaderLength
95 let payloadOff = off + frameHeaderLength
@@ -238,62 +209,6 @@ frameSender ctx@Context{outputQ,connectionWindow}
239----------------------------------------------------------------
210----------------------------------------------------------------
242−ResponseFile Status ResponseHeaders FilePath (Maybe FilePart)
243−ResponseBuilder Status ResponseHeaders Builder
244−ResponseStream Status ResponseHeaders StreamingBody
245−ResponseRaw (IO ByteString -> (ByteString -> IO ()) -> IO ()) Response
248−fillResponseBodyGetNext :: Connection -> InternalInfo -> Int -> WindowSize -> Response -> IO Next
249−fillResponseBodyGetNext Connection{connWriteBuffer,connBufferSize}
250− _ off lim (ResponseBuilder _ _ bb) = do
251− let datBuf = connWriteBuffer `plusPtr` off
252− room = min (connBufferSize - off) lim
253− (len, signal) <- B.runBuilder bb datBuf room
254− return $ nextForBuilder connWriteBuffer connBufferSize len signal
257−fillResponseBodyGetNext Connection{connWriteBuffer,connBufferSize}
258− _ off lim (ResponseFile _ _ path mpart) = do
259− let datBuf = connWriteBuffer `plusPtr` off
260− room = min (connBufferSize - off) lim
261− (start, bytes) <- fileStartEnd path mpart
262− -- fixme: how to close Handle? GC does it at this moment.
263− h <- IO.openBinaryFile path IO.ReadMode
264− IO.hSeek h IO.AbsoluteSeek start
265− len <- IO.hGetBufSome h datBuf (mini room bytes)
266− let bytes' = bytes - fromIntegral len
267− return $ nextForFile len connWriteBuffer connBufferSize h bytes' (return ())
269−fillResponseBodyGetNext Connection{connWriteBuffer,connBufferSize}
270− ii off lim (ResponseFile _ _ path mpart) = do
271− (fd, refresh) <- case fdCacher ii of
272− Just fdcache -> getFd fdcache path
274− fd' <- openFd path ReadOnly Nothing defaultFileFlags{nonBlock=True}
275− th <- T.register (timeoutManager ii) (closeFd fd')
276− return (fd', T.tickle th)
277− let datBuf = connWriteBuffer `plusPtr` off
278− room = min (connBufferSize - off) lim
279− (start, bytes) <- fileStartEnd path mpart
280− len <- positionRead fd datBuf (mini room bytes) start
282− let len' = fromIntegral len
283− return $ nextForFile len connWriteBuffer connBufferSize fd (start + len') (bytes - len') refresh
286−fillResponseBodyGetNext _ _ _ _ _ = error "fillResponseBodyGetNext"
288−fileStartEnd :: FilePath -> Maybe FilePart -> IO (Integer, Integer)
289−fileStartEnd path Nothing = do
290− end <- fromIntegral . P.fileSize <$> P.getFileStatus path
292−fileStartEnd _ (Just part) =
293− return (filePartOffset part, filePartByteCount part)
295−----------------------------------------------------------------
297fillStreamBodyGetNext :: Connection -> Int -> WindowSize -> TBQueue Sequence -> TVar Sync -> Stream -> IO Next
212fillStreamBodyGetNext :: Connection -> Int -> WindowSize -> TBQueue Sequence -> TVar Sync -> Stream -> IO Next
298fillStreamBodyGetNext Connection{connWriteBuffer,connBufferSize}
213fillStreamBodyGetNext Connection{connWriteBuffer,connBufferSize}
299 off lim sq tvar strm = do
214 off lim sq tvar strm = do
@@ -304,38 +219,6 @@ fillStreamBodyGetNext Connection{connWriteBuffer,connBufferSize}
305----------------------------------------------------------------
220----------------------------------------------------------------
307−fillBufBuilder :: Buffer -> BufSize -> Leftover -> DynaNext
308−fillBufBuilder buf0 siz0 leftover lim = do
309− let payloadBuf = buf0 `plusPtr` frameHeaderLength
310− room = min (siz0 - frameHeaderLength) lim
312− LZero -> error "fillBufBuilder: LZero"
314− (len, signal) <- writer payloadBuf room
317− | BS.length bs <= room -> do
318− buf1 <- copy payloadBuf bs
319− let len1 = BS.length bs
320− (len2, signal) <- writer buf1 (room - len1)
321− getNext (len1 + len2) signal
323− let (bs1,bs2) = BS.splitAt room bs
324− void $ copy payloadBuf bs1
325− getNext room (B.Chunk bs2 writer)
327− getNext l s = return $ nextForBuilder buf0 siz0 l s
329−nextForBuilder :: Buffer -> BufSize -> BytesFilled -> B.Next -> Next
330−nextForBuilder _ _ len B.Done
332−nextForBuilder buf siz len (B.More _ writer)
333− = Next len (CNext (fillBufBuilder buf siz (LOne writer)))
334−nextForBuilder buf siz len (B.Chunk bs writer)
335− = Next len (CNext (fillBufBuilder buf siz (LTwo bs writer)))
337−----------------------------------------------------------------
339runStreamBuilder :: Buffer -> BufSize -> TBQueue Sequence
222runStreamBuilder :: Buffer -> BufSize -> TBQueue Sequence
340 -> IO (Leftover, Maybe Trailers, BytesFilled)
223 -> IO (Leftover, Maybe Trailers, BytesFilled)
341runStreamBuilder buf0 room0 sq = loop buf0 room0 0
224runStreamBuilder buf0 room0 sq = loop buf0 room0 0
@@ -400,42 +283,3 @@ nextForStream buf siz sq tvar strm LZero Nothing len = do
400 return $ Next len CNone
283 return $ Next len CNone
401nextForStream buf siz sq tvar strm leftover Nothing len =
284nextForStream buf siz sq tvar strm leftover Nothing len =
402 return $ Next len (CNext (fillBufStream buf siz leftover sq tvar strm))
285 return $ Next len (CNext (fillBufStream buf siz leftover sq tvar strm))
404−----------------------------------------------------------------
407−fillBufFile :: Buffer -> BufSize -> IO.Handle -> Integer -> IO () -> DynaNext
408−fillBufFile buf siz h bytes refresh lim = do
409− let payloadBuf = buf `plusPtr` frameHeaderLength
410− room = min (siz - frameHeaderLength) lim
411− len <- IO.hGetBufSome h payloadBuf room
413− let bytes' = bytes - fromIntegral len
414− return $ nextForFile len buf siz h bytes' refresh
416−nextForFile :: BytesFilled -> Buffer -> BufSize -> IO.Handle -> Integer -> IO () -> Next
417−nextForFile 0 _ _ _ _ _ = Next 0 CFinish
418−nextForFile len _ _ _ 0 _ = Next len CFinish
419−nextForFile len buf siz h bytes refresh =
420− Next len (CNext (fillBufFile buf siz h bytes refresh))
422−fillBufFile :: Buffer -> BufSize -> Fd -> Integer -> Integer -> IO () -> DynaNext
423−fillBufFile buf siz fd start bytes refresh lim = do
424− let payloadBuf = buf `plusPtr` frameHeaderLength
425− room = min (siz - frameHeaderLength) lim
426− len <- positionRead fd payloadBuf (mini room bytes) start
427− let len' = fromIntegral len
429− return $ nextForFile len buf siz fd (start + len') (bytes - len') refresh
431−nextForFile :: BytesFilled -> Buffer -> BufSize -> Fd -> Integer -> Integer -> IO () -> Next
432−nextForFile 0 _ _ _ _ _ _ = Next 0 CFinish
433−nextForFile len _ _ _ _ 0 _ = Next len CFinish
434−nextForFile len buf siz fd start bytes refresh =
435− Next len (CNext (fillBufFile buf siz fd start bytes refresh))
438−mini :: Int -> Integer -> Int
440− | fromIntegral i < n = i
441− | otherwise = fromIntegral n