on master help sign in
Support sending promised streams in Sender
commit036b0662d50bff08729394deb177ec75e64d40f4 authorAndrew Pritchard <awpr@google.com> dateMon 3 Aug 2015, 13:51 (11 years ago) parent3875acf
3 files changed+31−5
wai/Network/Wai/HTTP2.hs+1 warp/Network/Wai/Handler/Warp/HTTP2/Sender.hs+27−4 warp/Network/Wai/Handler/Warp/HTTP2/Types.hs+3−1
wai/Network/Wai/HTTP2.hs+1
@@ -1,6 +1,7 @@
11{-# LANGUAGE EmptyCase, EmptyDataDecls, RankNTypes #-}
22module Network.Wai.HTTP2
33 ( Http2Application
4+ , PushPromise
45 , Response
56 , Trailers
67 , absurd
warp/Network/Wai/Handler/Warp/HTTP2/Sender.hs+27−4
@@ -11,12 +11,14 @@ import Control.Concurrent.STM
1111import qualified Control.Exception as E
1212import Control.Monad (unless, void, when)
1313import qualified Data.ByteString as BS
14+import qualified Data.ByteString.Builder as B (int32BE)
1415import qualified Data.ByteString.Builder.Extra as B
16+import Data.Monoid ((<>))
1517import Foreign.Ptr
1618import qualified Network.HTTP.Types as H
1719import Network.HTTP2
1820import Network.HTTP2.Priority
19−import Network.Wai.HTTP2 (Trailers)
21+import Network.Wai.HTTP2 (Trailers, absurd)
2022import Network.Wai.Handler.Warp.Buffer
2123import Network.Wai.Handler.Warp.HTTP2.EncodeFrame
2224import Network.Wai.Handler.Warp.HTTP2.HPACK
@@ -82,7 +84,7 @@ frameSender ctx@Context{outputQ,connectionWindow}
8284 switch (OFrame frame) = do
8385 connSendAll frame
8486 loop
85− switch out@(OResponse strm s h aux) = do
87+ switch (OResponse strm s h aux) = do
8688 unlessClosed ctx conn strm $
8789 getWindowSize connectionWindow (streamWindow strm) >>=
8890 sendResponse strm s h aux
@@ -95,6 +97,18 @@ frameSender ctx@Context{outputQ,connectionWindow}
9597 fillDataHeaderSend strm 0 datPayloadLen mnext
9698 maybeEnqueueNext strm mnext
9799 loop
100+ switch (OPush oldStrm push strm s h aux) = do
101+ unlessClosed ctx conn oldStrm $ do
102+ lim <- getWindowSize connectionWindow (streamWindow strm)
103+ -- Write and send the promise.
104+ builder <- hpackEncodeCIHeaders ctx $ absurd push
105+ off <- pushContinue (streamNumber oldStrm) (streamNumber strm) builder
106+ flushN $ off + frameHeaderLength
107+ -- TODO(awpr): refactor sendResponse to be able to handle non-zero
108+ -- initial offsets and use that to potentially avoid the extra syscall.
109+
110+ sendResponse strm s h aux lim
111+ loop
98112 switch (OTrailers strm []) = do
99113 let flag = setEndStream defaultFlags
100114 fillFrameHeader FrameData 0 (streamNumber strm) flag connWriteBuffer
@@ -141,8 +155,17 @@ frameSender ctx@Context{outputQ,connectionWindow}
141155 maybeEndHeaders B.Done = setEndHeader defaultFlags
142156 maybeEndHeaders _ = defaultFlags
143157
144− -- Write header and possibly continuation frames into the connection
145− -- buffer, using the given builder as their contents.
158+ -- Write PUSH_PROMISE and possibly CONTINUATION frames into the connection
159+ -- buffer, using the given builder as their contents; flush them to the
160+ -- socket as necessary.
161+ pushContinue sid newSid builder = do
162+ let builder' = B.int32BE (fromIntegral newSid) <> builder
163+ (len, signal) <- B.runBuilder builder' bufHeaderPayload headerPayloadLim
164+ let flag = maybeEndHeaders signal
165+ fillFrameHeader FramePushPromise len sid flag connWriteBuffer
166+ continue sid len signal
167+
168+ -- Write HEADER and possibly CONTINUATION frames.
146169 headerContinue sid builder endOfStream = do
147170 (len, signal) <- B.runBuilder builder bufHeaderPayload headerPayloadLim
148171 let flag0 = maybeEndHeaders signal
warp/Network/Wai/Handler/Warp/HTTP2/Types.hs+3−1
@@ -18,7 +18,7 @@ import Data.IntMap.Strict (IntMap, IntMap)
1818import qualified Data.IntMap.Strict as M
1919import qualified Network.HTTP.Types as H
2020import Network.Wai (Request)
21−import Network.Wai.HTTP2 (Trailers)
21+import Network.Wai.HTTP2 (PushPromise, Trailers)
2222import Network.Wai.Handler.Warp.IORef
2323import Network.Wai.Handler.Warp.Types
2424
@@ -69,6 +69,8 @@ data Output = OFinish
6969 | OResponse Stream H.Status H.ResponseHeaders Aux
7070 -- ^ Send the headers and as much of the response as is immediately
7171 -- available.
72+ | OPush Stream PushPromise Stream H.Status H.ResponseHeaders Aux
73+ -- ^ Send a PUSH_PROMISE frame, then act like OResponse.
7274 | ONext Stream DynaNext
7375 -- ^ Send a chunk of the response.
7476 | OTrailers Stream Trailers