on master help sign in
hashing ByteString only and cleaning up internal APIs.
commit857508a75a3c8c41df6b7c5dfd2d382e385daf4c authorKazu Yamamoto <kazu@iij.ad.jp> dateTue 23 Feb 2016, 14:19 (11 years ago) parent65ff57f
18 files changed+223−213
warp/Network/Wai/Handler/Warp.hs+1−1 warp/Network/Wai/Handler/Warp/Date.hs+2−11 warp/Network/Wai/Handler/Warp/FdCache.hs+55−52 warp/Network/Wai/Handler/Warp/FileInfoCache.hs+7−11 warp/Network/Wai/Handler/Warp/HTTP2.hs+5−5 warp/Network/Wai/Handler/Warp/HTTP2/HPACK.hs+2−2 warp/Network/Wai/Handler/Warp/HTTP2/Receiver.hs+4−4 warp/Network/Wai/Handler/Warp/HTTP2/Request.hs+13−8 warp/Network/Wai/Handler/Warp/HTTP2/Sender.hs+16−17 warp/Network/Wai/Handler/Warp/HTTP2/Types.hs+15−15 warp/Network/Wai/Handler/Warp/HTTP2/Worker.hs+16−19 warp/Network/Wai/Handler/Warp/HashMap.hs+5 warp/Network/Wai/Handler/Warp/Request.hs+14−10 warp/Network/Wai/Handler/Warp/Response.hs+11−27 warp/Network/Wai/Handler/Warp/Run.hs+22−20 warp/Network/Wai/Handler/Warp/SendFile.hs+3−3 warp/Network/Wai/Handler/Warp/Types.hs+30−6 warp/test/FdCacheSpec.hs+2−2
warp/Network/Wai/Handler/Warp.hs+1−1
@@ -108,7 +108,7 @@ import Network.Wai.Handler.Warp.Response (warpVersion)
108108import Network.Wai.Handler.Warp.Run
109109import Network.Wai.Handler.Warp.Settings
110110import Network.Wai.Handler.Warp.Timeout
111−import Network.Wai.Handler.Warp.Types
111+import Network.Wai.Handler.Warp.Types hiding (getFileInfo)
112112
113113-- | Port to listen on. Default value: 3000
114114--
warp/Network/Wai/Handler/Warp/Date.hs+2−11
@@ -2,8 +2,6 @@
22
33module Network.Wai.Handler.Warp.Date (
44 withDateCache
5− , getDate
6− , DateCache
75 , GMTDate
86 ) where
97
@@ -25,22 +23,15 @@ import System.Posix (epochTime)
2523-- | The type of the Date header value.
2624type GMTDate = ByteString
2725
28−-- | The type of the cache of the Date header value.
29−type DateCache = IO GMTDate
30−
3126-- | Creating 'DateCache' and executing the action.
32−withDateCache :: (DateCache -> IO a) -> IO a
27+withDateCache :: (IO GMTDate -> IO a) -> IO a
3328withDateCache action = initialize >>= action
3429
35−initialize :: IO DateCache
30+initialize :: IO (IO GMTDate)
3631initialize = mkAutoUpdate defaultUpdateSettings {
3732 updateAction = formatHTTPDate <$> getCurrentHTTPDate
3833 }
3934
40−-- | Getting current 'GMTDate' based on 'DateCache'.
41−getDate :: DateCache -> IO GMTDate
42−getDate = id
43−
4435#ifdef WINDOWS
4536uToH :: UTCTime -> HTTPDate
4637uToH = epochTimeToHTTPDate . CTime . truncate . utcTimeToPOSIXSeconds
warp/Network/Wai/Handler/Warp/FdCache.hs+55−52
@@ -2,47 +2,59 @@
22
33-- | File descriptor cache to avoid locks in kernel.
44
5−#ifdef WINDOWS
65module Network.Wai.Handler.Warp.FdCache (
76 withFdCache
8− , MutableFdCache
7+ , Fd
98 , Refresh
9+#ifndef WINDOWS
10+ , openFile
11+ , closeFile
12+#endif
1013 ) where
1114
12−type Refresh = IO ()
13−type MutableFdCache = ()
14−
15−withFdCache :: Int -> (Maybe MutableFdCache -> IO a) -> IO a
16−withFdCache _ f = f Nothing
15+#ifdef WINDOWS
16+type Fd = ()
1717#else
18−module Network.Wai.Handler.Warp.FdCache (
19− withFdCache
20− , getFd
21− , getFd'
22− , MutableFdCache
23− , Refresh
24− ) where
25−
2618#if __GLASGOW_HASKELL__ < 709
2719import Control.Applicative ((<$>), (<*>))
2820#endif
2921import Control.Exception (bracket)
30−import Data.Hashable (hash)
3122import Network.Wai.Handler.Warp.IORef
3223import Network.Wai.Handler.Warp.MultiMap
24+import Control.Reaper
3325import System.Posix.IO (openFd, OpenFileFlags(..), defaultFileFlags, OpenMode(ReadOnly), closeFd)
3426import System.Posix.Types (Fd)
35−import Control.Reaper
27+#endif
3628
3729----------------------------------------------------------------
3830
39−data Status = Active | Inactive
40−
41−newtype MutableStatus = MutableStatus (IORef Status)
31+type Hash = Int
4232
4333-- | An action to activate a Fd cache entry.
4434type Refresh = IO ()
4535
36+getFdNothing :: Hash -> FilePath -> IO (Maybe Fd, Refresh)
37+getFdNothing _ _ = return (Nothing, return ())
38+
39+----------------------------------------------------------------
40+
41+-- | Creating 'MutableFdCache' and executing the action in the second
42+-- argument. The first argument is a cache duration in second.
43+withFdCache :: Int -> ((Hash -> FilePath -> IO (Maybe Fd, Refresh)) -> IO a) -> IO a
44+#ifdef WINDOWS
45+withFdCache _ action = action getFdNothing
46+#else
47+withFdCache 0 action = action getFdNothing
48+withFdCache duration action = bracket (initialize duration)
49+ terminate
50+ (\mfc -> action (getFd mfc))
51+
52+----------------------------------------------------------------
53+
54+data Status = Active | Inactive
55+
56+newtype MutableStatus = MutableStatus (IORef Status)
57+
4658status :: MutableStatus -> IO Status
4759status (MutableStatus ref) = readIORef ref
4860
@@ -59,14 +71,17 @@ inactive (MutableStatus ref) = writeIORef ref Inactive
5971
6072data FdEntry = FdEntry !FilePath !Fd !MutableStatus
6173
74+openFile :: FilePath -> IO Fd
75+openFile path = openFd path ReadOnly Nothing defaultFileFlags{nonBlock=True}
76+
77+closeFile :: Fd -> IO ()
78+closeFile = closeFd
79+
6280newFdEntry :: FilePath -> IO FdEntry
63−newFdEntry path = FdEntry path
64− <$> openFd path ReadOnly Nothing defaultFileFlags{nonBlock=True}
65− <*> newActiveStatus
81+newFdEntry path = FdEntry path <$> openFile path <*> newActiveStatus
6682
6783----------------------------------------------------------------
6884
69−type Hash = Int
7085type FdCache = MMap Hash FdEntry
7186
7287-- | Mutable Fd cacher.
@@ -87,25 +102,17 @@ look mfc path key = searchWith key check <$> fdCache mfc
87102
88103----------------------------------------------------------------
89104
90−-- | Creating 'MutableFdCache' and executing the action in the second
91−-- argument. The first argument is a cache duration in second.
92−withFdCache :: Int -> (Maybe MutableFdCache -> IO a) -> IO a
93−withFdCache duration action = bracket (initialize duration)
94− terminate
95− action
96−
97−----------------------------------------------------------------
98−
99105-- The first argument is a cache duration in second.
100−initialize :: Int -> IO (Maybe MutableFdCache)
101−initialize 0 = return Nothing
102−initialize duration = Just . MutableFdCache <$> mkReaper defaultReaperSettings
103− { reaperAction = clean
104− , reaperDelay = duration
105− , reaperCons = uncurry insert
106− , reaperNull = isEmpty
107− , reaperEmpty = empty
108− }
106+initialize :: Int -> IO MutableFdCache
107+initialize duration = MutableFdCache <$> mkReaper settings
108+ where
109+ settings = defaultReaperSettings {
110+ reaperAction = clean
111+ , reaperDelay = duration
112+ , reaperCons = uncurry insert
113+ , reaperNull = isEmpty
114+ , reaperEmpty = empty
115+ }
109116
110117clean :: FdCache -> IO (FdCache -> FdCache)
111118clean old = do
@@ -130,9 +137,8 @@ prune k (Tom ent@(FdEntry _ fd mst) vs) = status mst >>= prune'
130137
131138----------------------------------------------------------------
132139
133−terminate :: Maybe MutableFdCache -> IO ()
134−terminate Nothing = return ()
135−terminate (Just (MutableFdCache reaper)) = do
140+terminate :: MutableFdCache -> IO ()
141+terminate (MutableFdCache reaper) = do
136142 !t <- reaperStop reaper
137143 mapM_ closeIt $ toList t
138144 where
@@ -140,18 +146,15 @@ terminate (Just (MutableFdCache reaper)) = do
140146
141147----------------------------------------------------------------
142148
143−getFd :: MutableFdCache -> FilePath -> IO (Fd, Refresh)
144−getFd mfc path = getFd' mfc (hash path) path
145−
146149-- | Getting 'Fd' and 'Refresh' from the mutable Fd cacher.
147−getFd' :: MutableFdCache -> Hash -> FilePath -> IO (Fd, Refresh)
148−getFd' mfc@(MutableFdCache reaper) h path = look mfc path h >>= get
150+getFd :: MutableFdCache -> Hash -> FilePath -> IO (Maybe Fd, Refresh)
151+getFd mfc@(MutableFdCache reaper) h path = look mfc path h >>= get
149152 where
150153 get Nothing = do
151154 ent@(FdEntry _ fd mst) <- newFdEntry path
152155 reaperAdd reaper (h, ent)
153− return (fd, refresh mst)
156+ return (Just fd, refresh mst)
154157 get (Just (FdEntry _ fd mst)) = do
155158 refresh mst
156− return (fd, refresh mst)
159+ return (Just fd, refresh mst)
157160#endif
warp/Network/Wai/Handler/Warp/FileInfoCache.hs+7−11
@@ -11,7 +11,6 @@ import Control.Exception as E
1111import Control.Monad (void)
1212import Control.Reaper
1313import Data.ByteString (ByteString)
14−import Data.Hashable (hash)
1514import Network.HTTP.Date
1615import Network.Wai.Handler.Warp.HashMap (HashMap)
1716import qualified Network.Wai.Handler.Warp.HashMap as M
@@ -55,16 +54,13 @@ getInfo path = do
5554 else
5655 throwIO (userError "FileInfoCache:getInfo")
5756
58−getInfo' :: Hash -> FilePath -> IO FileInfo
59−getInfo' _ = getInfo
57+getInfoNaive :: Hash -> FilePath -> IO FileInfo
58+getInfoNaive _ = getInfo
6059
6160----------------------------------------------------------------
6261
63−getAndRegisterInfo :: FileInfoCache -> FilePath -> IO FileInfo
64−getAndRegisterInfo reaper path = getAndRegisterInfo' reaper (hash path) path
65−
66−getAndRegisterInfo' :: FileInfoCache -> Hash -> FilePath -> IO FileInfo
67−getAndRegisterInfo' reaper@Reaper{..} h path = do
62+getAndRegisterInfo :: FileInfoCache -> Hash -> FilePath -> IO FileInfo
63+getAndRegisterInfo reaper@Reaper{..} h path = do
6864 cache <- reaperRead
6965 case M.lookup h path cache of
7066 Just Negative -> throwIO (userError "FileInfoCache:getAndRegisterInfo")
@@ -89,13 +85,13 @@ negative Reaper{..} h path = do
8985-- and executing the action in the second argument.
9086-- The first argument is a cache duration in second.
9187withFileInfoCache :: Int
92− -> ((FilePath -> IO FileInfo) -> (Hash -> FilePath -> IO FileInfo) -> IO a)
88+ -> ((Hash -> FilePath -> IO FileInfo) -> IO a)
9389 -> IO a
94−withFileInfoCache 0 action = action getInfo getInfo'
90+withFileInfoCache 0 action = action getInfoNaive
9591withFileInfoCache duration action =
9692 E.bracket (initialize duration)
9793 terminate
98− (\r -> action (getAndRegisterInfo r) (getAndRegisterInfo' r))
94+ (\r -> action (getAndRegisterInfo r))
9995
10096initialize :: Hash -> IO FileInfoCache
10197initialize duration = mkReaper settings
warp/Network/Wai/Handler/Warp/HTTP2.hs+5−5
@@ -22,15 +22,15 @@ import Network.Wai.Handler.Warp.Types
2222
2323----------------------------------------------------------------
2424
25−http2 :: Connection -> InternalInfo -> SockAddr -> Transport -> S.Settings -> (BufSize -> IO ByteString) -> Application -> IO ()
26−http2 conn ii addr transport settings readN app = do
25+http2 :: Connection -> InternalInfo1 -> SockAddr -> Transport -> S.Settings -> (BufSize -> IO ByteString) -> Application -> IO ()
26+http2 conn ii1 addr transport settings readN app = do
2727 checkTLS
2828 ok <- checkPreface
2929 when ok $ do
3030 ctx <- newContext
3131 -- Workers, worker manager and timer manager
3232 mgr <- start settings
33− let responder = response ii settings ctx mgr
33+ let responder = response settings ctx mgr
3434 action = worker ctx settings app responder
3535 setAction mgr action
3636 -- The number of workers is 3.
@@ -40,12 +40,12 @@ http2 conn ii addr transport settings readN app = do
4040 -- context switches happen.
4141 replicateM_ 3 $ spawnAction mgr
4242 -- Receiver
43− let mkreq = mkRequest ii settings addr
43+ let mkreq = mkRequest ii1 settings addr
4444 tid <- forkIO $ frameReceiver ctx mkreq readN
4545 -- Sender
4646 -- frameSender is the main thread because it ensures to send
4747 -- a goway frame.
48− frameSender ctx conn ii settings mgr `E.finally` do
48+ frameSender ctx conn settings mgr `E.finally` do
4949 clearContext ctx
5050 stop mgr
5151 killThread tid
warp/Network/Wai/Handler/Warp/HTTP2/HPACK.hs+2−2
@@ -34,10 +34,10 @@ hpackEncodeHeader Context{..} buf siz ii settings s hdr0 = do
3434 encodeHeaderBuffer buf siz strategy True encodeDynamicTable hs
3535 where
3636 status = B8.pack $ show $ H.statusCode s
37− dc = dateCacher ii
37+ getdate = getDate ii
3838 rspidxhdr = indexResponseHeader hdr0
3939 defServer = S.settingsServerName settings
40− addServerAndDate = addDate dc rspidxhdr . addServer defServer rspidxhdr
40+ addServerAndDate = addDate getdate rspidxhdr . addServer defServer rspidxhdr
4141
4242hpackEncodeHeaderLoop :: Context -> Buffer -> BufSize -> HeaderList
4343 -> IO (HeaderList, Int)
warp/Network/Wai/Handler/Warp/HTTP2/Receiver.hs+4−4
@@ -111,8 +111,8 @@ frameReceiver ctx mkreq recvN = loop 0 `E.catch` sendGoaway
111111 E.throwIO $ StreamError ProtocolError streamId
112112 writeIORef streamPrecedence $ toPrecedence pri
113113 writeIORef streamState HalfClosed
114− let !req = mkreq vh (return "")
115− atomically $ writeTQueue inputQ $ Input strm req
114+ let (!req, !ii) = mkreq vh (return "")
115+ atomically $ writeTQueue inputQ $ Input strm req ii
116116 Nothing -> E.throwIO $ StreamError ProtocolError streamId
117117 Open (HasBody hdr pri) -> do
118118 resetContinued
@@ -124,8 +124,8 @@ frameReceiver ctx mkreq recvN = loop 0 `E.catch` sendGoaway
124124 writeIORef streamContentLength $ vhCL vh
125125 readQ <- newReadBody q
126126 bodySource <- mkSource readQ
127− let !req = mkreq vh (readSource bodySource)
128− atomically $ writeTQueue inputQ $ Input strm req
127+ let (!req, !ii) = mkreq vh (readSource bodySource)
128+ atomically $ writeTQueue inputQ $ Input strm req ii
129129 Nothing -> E.throwIO $ StreamError ProtocolError streamId
130130 s@(Open Continued{}) -> do
131131 setContinued
warp/Network/Wai/Handler/Warp/HTTP2/Request.hs+13−8
@@ -30,11 +30,12 @@ import Network.HTTP.Types (RequestHeaders)
3030import qualified Network.HTTP.Types as H
3131import Network.Socket (SockAddr)
3232import Network.Wai
33−import Network.Wai.Internal (Request(..))
3433import Network.Wai.Handler.Warp.HTTP2.Types
34+import Network.Wai.Handler.Warp.HashMap (hashByteString)
3535import Network.Wai.Handler.Warp.ReadInt
3636import Network.Wai.Handler.Warp.Request (pauseTimeoutKey, getFileInfoKey)
37−import Network.Wai.Handler.Warp.Types (InternalInfo(..))
37+import Network.Wai.Handler.Warp.Types
38+import Network.Wai.Internal (Request(..))
3839import qualified Network.Wai.Handler.Warp.Settings as S (Settings, settingsNoParsePath)
3940import qualified Network.Wai.Handler.Warp.Timeout as Timeout
4041
@@ -49,23 +50,26 @@ data ValidHeaders = ValidHeaders {
4950 , vhHeader :: !RequestHeaders
5051 } deriving Show
5152
52−type MkReq = ValidHeaders -> IO ByteString -> Request
53+type MkReq = ValidHeaders -> IO ByteString -> (Request,InternalInfo)
5354
54−mkRequest :: InternalInfo -> S.Settings -> SockAddr -> MkReq
55−mkRequest ii settings addr (ValidHeaders m p ma mrng mrr mua _ hdr) body = req
55+mkRequest :: InternalInfo1 -> S.Settings -> SockAddr -> MkReq
56+mkRequest ii1 settings addr (ValidHeaders m p ma mrng mrr mua _ hdr) body =
57+ (req,ii)
5658 where
5759 (unparsedPath,query) = B8.break (=='?') p
5860 !path = H.extractPath unparsedPath
61+ !rawPath = if S.settingsNoParsePath settings then unparsedPath else path
62+ !h = hashByteString rawPath
5963 !req = Request {
6064 requestMethod = m
6165 , httpVersion = http2ver
62− , rawPathInfo = if S.settingsNoParsePath settings then unparsedPath else path
66+ , rawPathInfo = rawPath
6367 , pathInfo = H.decodePathSegments path
6468 , rawQueryString = query
6569 , queryString = H.parseQuery query
6670 , requestHeaders = case ma of
6771 Nothing -> hdr
68− Just h -> (mk "host", h) : hdr
72+ Just hv -> (mk "host", hv) : hdr
6973 , isSecure = True
7074 , remoteHost = addr
7175 , requestBody = body
@@ -76,9 +80,10 @@ mkRequest ii settings addr (ValidHeaders m p ma mrng mrr mua _ hdr) body = req
7680 , requestHeaderReferer = mrr
7781 , requestHeaderUserAgent = mua
7882 }
83+ !ii = toInternalInfo ii1 h
7984 !th = threadHandle ii
8085 !vaultValue = Vault.insert pauseTimeoutKey (Timeout.pause th)
81− $ Vault.insert getFileInfoKey (fileInfo ii)
86+ $ Vault.insert getFileInfoKey (getFileInfo ii)
8287 Vault.empty
8388
8489----------------------------------------------------------------
warp/Network/Wai/Handler/Warp/HTTP2/Sender.hs+16−17
@@ -34,8 +34,6 @@ import qualified System.IO as IO
3434import Network.Wai.Handler.Warp.FdCache
3535import Network.Wai.Handler.Warp.SendFile (positionRead)
3636import qualified Network.Wai.Handler.Warp.Timeout as T
37−import System.Posix.IO (openFd, OpenFileFlags(..), defaultFileFlags, OpenMode(ReadOnly), closeFd)
38−import System.Posix.Types
3937#endif
4038
4139----------------------------------------------------------------
@@ -63,10 +61,10 @@ data Switch = C Control
6361 | O (StreamId,Precedence,Output)
6462 | Flush
6563
66−frameSender :: Context -> Connection -> InternalInfo -> S.Settings -> Manager -> IO ()
64+frameSender :: Context -> Connection -> S.Settings -> Manager -> IO ()
6765frameSender ctx@Context{outputQ,controlQ,connectionWindow,encodeDynamicTable}
6866 conn@Connection{connWriteBuffer,connBufferSize,connSendAll}
69− ii settings mgr = loop 0 `E.catch` ignore
67+ settings mgr = loop 0 `E.catch` ignore
7068 where
7169 dequeue off = do
7270 isEmpty <- isEmptyTQueue controlQ
@@ -117,23 +115,23 @@ frameSender ctx@Context{outputQ,controlQ,connectionWindow,encodeDynamicTable}
117115 maybeEnqueueNext strm mtbq mnext
118116 return off
119117
120− output (ORspn strm rspn) off0 lim = do
118+ output (ORspn strm rspn ii) off0 lim = do
121119 -- Header frame and Continuation frame
122120 let sid = streamNumber strm
123121 endOfStream = case rspn of
124122 RspnNobody _ _ -> True
125123 _ -> False
126− kvlen <- headerContinue sid rspn endOfStream off0
124+ kvlen <- headerContinue sid rspn endOfStream off0 ii
127125 off <- sendHeadersIfNecessary $ off0 + frameHeaderLength + kvlen
128126 case rspn of
129127 RspnNobody _ _ -> do
130128 closed ctx strm Finished
131129 return off
132− RspnFile _ _ h path mpart -> do
130+ RspnFile _ _ path mpart -> do
133131 -- Data frame payload
134132 let payloadOff = off + frameHeaderLength
135133 Next datPayloadLen mnext <-
136− fillFileBodyGetNext conn ii payloadOff lim h path mpart
134+ fillFileBodyGetNext conn ii payloadOff lim path mpart
137135 off' <- fillDataHeader strm off datPayloadLen mnext
138136 maybeEnqueueNext strm Nothing mnext
139137 return off'
@@ -190,7 +188,7 @@ frameSender ctx@Context{outputQ,controlQ,connectionWindow,encodeDynamicTable}
190188 flushN :: Int -> IO ()
191189 flushN n = bufferIO connWriteBuffer n connSendAll
192190
193− headerContinue sid rspn endOfStream off = do
191+ headerContinue sid rspn endOfStream off ii = do
194192 let !s = rspnStatus rspn
195193 !h = rspnHeaders rspn
196194 let !offkv = off + frameHeaderLength
@@ -274,10 +272,10 @@ fillBuilderBodyGetNext Connection{connWriteBuffer,connBufferSize}
274272 (len, signal) <- B.runBuilder bb datBuf room
275273 return $ nextForBuilder len signal
276274
277−fillFileBodyGetNext :: Connection -> InternalInfo -> Int -> WindowSize -> Int -> FilePath -> Maybe FilePart -> IO Next
275+fillFileBodyGetNext :: Connection -> InternalInfo -> Int -> WindowSize -> FilePath -> Maybe FilePart -> IO Next
278276#ifdef WINDOWS
279277fillFileBodyGetNext Connection{connWriteBuffer,connBufferSize}
280− _ off lim _ path mpart = do
278+ _ off lim path mpart = do
281279 let datBuf = connWriteBuffer `plusPtr` off
282280 room = min (connBufferSize - off) lim
283281 (start, bytes) <- fileStartEnd path mpart
@@ -290,13 +288,14 @@ fillFileBodyGetNext Connection{connWriteBuffer,connBufferSize}
290288 return $ nextForFile len hdl bytes' (return ())
291289#else
292290fillFileBodyGetNext Connection{connWriteBuffer,connBufferSize}
293− ii off lim h path mpart = do
294− (fd, refresh) <- case fdCacher ii of
295− Just fdcache -> getFd' fdcache h path
296− Nothing -> do
297− fd' <- openFd path ReadOnly Nothing defaultFileFlags{nonBlock=True}
298− th <- T.register (timeoutManager ii) (closeFd fd')
291+ ii off lim path mpart = do
292+ (mfd, refresh') <- getFd ii path
293+ (fd, refresh) <- case mfd of
294+ Nothing -> do
295+ fd' <- openFile path
296+ th <- T.register (timeoutManager ii) (closeFile fd')
299297 return (fd', T.tickle th)
298+ Just fd -> return (fd, refresh')
300299 let datBuf = connWriteBuffer `plusPtr` off
301300 room = min (connBufferSize - off) lim
302301 (start, bytes) <- fileStartEnd path mpart
warp/Network/Wai/Handler/Warp/HTTP2/Types.hs+15−15
@@ -41,7 +41,7 @@ isHTTP2 tls = useHTTP2
4141
4242----------------------------------------------------------------
4343
44−data Input = Input Stream Request
44+data Input = Input Stream Request InternalInfo
4545
4646----------------------------------------------------------------
4747
@@ -54,31 +54,31 @@ data Next = Next !BytesFilled (Maybe DynaNext)
5454data Rspn = RspnNobody H.Status H.ResponseHeaders
5555 | RspnStreaming H.Status H.ResponseHeaders (TBQueue Sequence)
5656 | RspnBuilder H.Status H.ResponseHeaders Builder
57− | RspnFile H.Status H.ResponseHeaders Int FilePath (Maybe FilePart)
57+ | RspnFile H.Status H.ResponseHeaders FilePath (Maybe FilePart)
5858
5959rspnStatus :: Rspn -> H.Status
60−rspnStatus (RspnNobody s _) = s
61−rspnStatus (RspnStreaming s _ _) = s
62−rspnStatus (RspnBuilder s _ _) = s
63−rspnStatus (RspnFile s _ _ _ _ ) = s
60+rspnStatus (RspnNobody s _) = s
61+rspnStatus (RspnStreaming s _ _) = s
62+rspnStatus (RspnBuilder s _ _) = s
63+rspnStatus (RspnFile s _ _ _ ) = s
6464
6565rspnHeaders :: Rspn -> H.ResponseHeaders
66−rspnHeaders (RspnNobody _ h) = h
67−rspnHeaders (RspnStreaming _ h _) = h
68−rspnHeaders (RspnBuilder _ h _) = h
69−rspnHeaders (RspnFile _ h _ _ _ ) = h
66+rspnHeaders (RspnNobody _ h) = h
67+rspnHeaders (RspnStreaming _ h _) = h
68+rspnHeaders (RspnBuilder _ h _) = h
69+rspnHeaders (RspnFile _ h _ _ ) = h
7070
71−data Output = ORspn !Stream !Rspn
71+data Output = ORspn !Stream !Rspn !InternalInfo
7272 | ONext !Stream !DynaNext !(Maybe (TBQueue Sequence))
7373
7474outputStream :: Output -> Stream
75−outputStream (ORspn strm _) = strm
75+outputStream (ORspn strm _ _) = strm
7676outputStream (ONext strm _ _) = strm
7777
7878outputMaybeTBQueue :: Output -> Maybe (TBQueue Sequence)
79−outputMaybeTBQueue (ORspn _ (RspnStreaming _ _ tbq)) = Just tbq
80−outputMaybeTBQueue (ORspn _ _) = Nothing
81−outputMaybeTBQueue (ONext _ _ mtbq) = mtbq
79+outputMaybeTBQueue (ORspn _ (RspnStreaming _ _ tbq) _) = Just tbq
80+outputMaybeTBQueue (ORspn _ _ _) = Nothing
81+outputMaybeTBQueue (ONext _ _ mtbq) = mtbq
8282
8383data Control = CFinish
8484 | CGoaway !ByteString
warp/Network/Wai/Handler/Warp/HTTP2/Worker.hs+16−19
@@ -20,7 +20,6 @@ import Control.Exception (SomeException(..), AsyncException(..))
2020import qualified Control.Exception as E
2121import Control.Monad (when)
2222import Data.ByteString.Builder (byteString)
23−import Data.Hashable (hash)
2423import qualified Network.HTTP.Types as H
2524import Network.HTTP2
2625import Network.Wai
@@ -42,14 +41,14 @@ import Network.Wai.Internal (Response(..), ResponseReceived(..), ResponseReceive
4241-- | The wai definition is 'type Application = Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived'.
4342-- This type implements the second argument (Response -> IO ResponseReceived)
4443-- with extra arguments.
45−type Responder = ThreadContinue -> T.Handle -> Stream -> Request ->
44+type Responder = InternalInfo -> ThreadContinue -> Stream -> Request ->
4645 Response -> IO ResponseReceived
4746
4847-- | This function is passed to workers.
4948-- They also pass 'Response's from 'Application's to this function.
5049-- This function enqueues commands for the HTTP/2 sender.
51−response :: InternalInfo -> S.Settings -> Context -> Manager -> Responder
52−response ii settings Context{outputQ} mgr tconf th strm req rsp
50+response :: S.Settings -> Context -> Manager -> Responder
51+response settings Context{outputQ} mgr ii tconf strm req rsp
5352 | R.hasBody s0 = case rsp of
5453 ResponseStream _ _ strmbdy
5554 | isHead -> responseNoBody s0 hs0
@@ -65,6 +64,7 @@ response ii settings Context{outputQ} mgr tconf th strm req rsp
6564 !s0 = responseStatus rsp
6665 !hs0 = responseHeaders rsp
6766 !logger = S.settingsLogger settings
67+ !th = threadHandle ii
6868
6969 -- Ideally, log messages should be written when responses are
7070 -- actually sent. But there is no way to keep good memory usage
@@ -76,7 +76,7 @@ response ii settings Context{outputQ} mgr tconf th strm req rsp
7676 logger req s Nothing
7777 setThreadContinue tconf True
7878 let rspn = RspnNobody s hs
79− out = ORspn strm rspn
79+ out = ORspn strm rspn ii
8080 enqueueOutput outputQ out
8181 return ResponseReceived
8282
@@ -84,32 +84,29 @@ response ii settings Context{outputQ} mgr tconf th strm req rsp
8484 logger req s Nothing
8585 setThreadContinue tconf True
8686 let rspn = RspnBuilder s hs bdy
87− out = ORspn strm rspn
87+ out = ORspn strm rspn ii
8888 enqueueOutput outputQ out
8989 return ResponseReceived
9090
9191 responseFileXXX path Nothing = do
92− let !h = hash $ rawPathInfo req
93− efinfo <- E.try $ fileInfo' ii h path
92+ efinfo <- E.try $ getFileInfo ii path
9493 case efinfo of
9594 Left (_ex :: E.IOException) -> response404
9695 Right finfo -> case conditionalRequest finfo hs0 (indexRequestHeader (requestHeaders req)) of
9796 WithoutBody s -> responseNoBody s hs0
98− WithBody s hs beg len -> responseFile2XX s hs h path (Just (FilePart beg len (fileInfoSize finfo)))
97+ WithBody s hs beg len -> responseFile2XX s hs path (Just (FilePart beg len (fileInfoSize finfo)))
9998
100− responseFileXXX path mpart = responseFile2XX s0 hs0 h path mpart
101− where
102− !h = hash $ rawPathInfo req
99+ responseFileXXX path mpart = responseFile2XX s0 hs0 path mpart
103100
104− responseFile2XX s hs h path mpart
101+ responseFile2XX s hs path mpart
105102 | isHead = do
106103 logger req s Nothing
107104 responseNoBody s hs
108105 | otherwise = do
109106 logger req s (filePartByteCount <$> mpart)
110107 setThreadContinue tconf True
111− let rspn = RspnFile s hs h path mpart
112− out = ORspn strm rspn
108+ let rspn = RspnFile s hs path mpart
109+ out = ORspn strm rspn ii
113110 enqueueOutput outputQ out
114111 return ResponseReceived
115112
@@ -134,7 +131,7 @@ response ii settings Context{outputQ} mgr tconf th strm req rsp
134131 -- So, let's serialize 'Builder' with a designated queue.
135132 tbq <- newTBQueueIO 10 -- fixme: hard coding: 10
136133 let rspn = RspnStreaming s0 hs0 tbq
137− out = ORspn strm rspn
134+ out = ORspn strm rspn ii
138135 enqueueOutput outputQ out
139136 let push b = do
140137 atomically $ writeTBQueue tbq (SBuilder b)
@@ -155,11 +152,11 @@ worker ctx@Context{inputQ,controlQ} set app responder tm = do
155152 setThreadContinue tcont True
156153 ex <- E.try $ do
157154 T.pause th
158− inp@(Input strm req) <- atomically $ readTQueue inputQ
155+ inp@(Input strm req ii) <- atomically $ readTQueue inputQ
159156 setStreamInfo sinfo inp
160157 T.resume th
161158 T.tickle th
162− app req $ responder tcont th strm req
159+ app req $ responder ii tcont strm req
163160 cont1 <- case ex of
164161 Right ResponseReceived -> return True
165162 Left e@(SomeException _)
@@ -179,7 +176,7 @@ worker ctx@Context{inputQ,controlQ} set app responder tm = do
179176 minp <- getStreamInfo sinfo
180177 case minp of
181178 Nothing -> return ()
182− Just (Input strm req) -> do
179+ Just (Input strm req _ii) -> do
183180 closed ctx strm Killed
184181 let frame = resetFrame InternalError (streamNumber strm)
185182 enqueueControl controlQ $ CFrame frame
warp/Network/Wai/Handler/Warp/HashMap.hs+5
@@ -1,5 +1,7 @@
11module Network.Wai.Handler.Warp.HashMap where
22
3+import Data.ByteString (ByteString)
4+import Data.Hashable (hash)
35import Data.IntMap.Strict (IntMap)
46import qualified Data.IntMap.Strict as I
57import Data.Map.Strict (Map)
@@ -8,6 +10,9 @@ import qualified Data.Map.Strict as M
810type Hash = Int
911newtype HashMap k v = HashMap (IntMap (Map k v))
1012
13+hashByteString :: ByteString -> Hash
14+hashByteString = hash
15+
1116empty :: HashMap k v
1217empty = HashMap $ I.empty
1318
warp/Network/Wai/Handler/Warp/Request.hs+14−10
@@ -23,6 +23,7 @@ import Network.Socket (SockAddr)
2323import Network.Wai
2424import Network.Wai.Handler.Warp.Conduit
2525import Network.Wai.Handler.Warp.FileInfoCache
26+import Network.Wai.Handler.Warp.HashMap (hashByteString)
2627import Network.Wai.Handler.Warp.Header
2728import Network.Wai.Handler.Warp.ReadInt
2829import Network.Wai.Handler.Warp.RequestHeader
@@ -47,19 +48,20 @@ maxTotalHeaderLength = 50 * 1024
4748-- to create 'Request'.
4849recvRequest :: Settings
4950 -> Connection
50− -> InternalInfo
51+ -> InternalInfo1
5152 -> SockAddr -- ^ Peer's address.
5253 -> Source -- ^ Where HTTP request comes from.
5354 -> IO (Request
5455 ,Maybe (I.IORef Int)
5556 ,IndexedHeader
56− ,IO ByteString) -- ^
57+ ,IO ByteString
58+ ,InternalInfo) -- ^
5759 -- 'Request' passed to 'Application',
5860 -- how many bytes remain to be consumed, if known
5961 -- 'IndexedHeader' of HTTP request for internal use,
6062 -- Body producing action used for flushing the request body
6163
62−recvRequest settings conn ii addr src = do
64+recvRequest settings conn ii1 addr src = do
6365 hdrlines <- headerLines src
6466 (method, unparsedPath, path, query, httpversion, hdr) <- parseHeaderLines hdrlines
6567 let idxhdr = indexRequestHeader hdr
@@ -67,6 +69,13 @@ recvRequest settings conn ii addr src = do
6769 cl = idxhdr ! fromEnum ReqContentLength
6870 te = idxhdr ! fromEnum ReqTransferEncoding
6971 handle100Continue = handleExpect conn httpversion expect
72+ rawPath = if settingsNoParsePath settings then unparsedPath else path
73+ h = hashByteString rawPath
74+ ii = toInternalInfo ii1 h
75+ th = threadHandle ii
76+ vaultValue = Vault.insert pauseTimeoutKey (Timeout.pause th)
77+ $ Vault.insert getFileInfoKey (getFileInfo ii)
78+ Vault.empty
7079 (rbody, remainingRef, bodyLength) <- bodyAndSource src cl te
7180 -- body producing function which will produce '100-continue', if needed
7281 rbody' <- timeoutBody remainingRef th rbody handle100Continue
@@ -76,7 +85,7 @@ recvRequest settings conn ii addr src = do
7685 requestMethod = method
7786 , httpVersion = httpversion
7887 , pathInfo = H.decodePathSegments path
79− , rawPathInfo = if settingsNoParsePath settings then unparsedPath else path
88+ , rawPathInfo = rawPath
8089 , rawQueryString = query
8190 , queryString = H.parseQuery query
8291 , requestHeaders = hdr
@@ -90,12 +99,7 @@ recvRequest settings conn ii addr src = do
9099 , requestHeaderReferer = idxhdr ! fromEnum ReqReferer
91100 , requestHeaderUserAgent = idxhdr ! fromEnum ReqUserAgent
92101 }
93− return (req, remainingRef, idxhdr, rbodyFlush)
94− where
95− th = threadHandle ii
96− vaultValue = Vault.insert pauseTimeoutKey (Timeout.pause th)
97− $ Vault.insert getFileInfoKey (fileInfo ii)
98− Vault.empty
102+ return (req, remainingRef, idxhdr, rbodyFlush, ii)
99103
100104----------------------------------------------------------------
101105
warp/Network/Wai/Handler/Warp/Response.hs+11−27
@@ -36,7 +36,6 @@ import Data.ByteString.Builder (byteString, Builder)
3636import Data.ByteString.Builder.Extra (flush)
3737import qualified Data.CaseInsensitive as CI
3838import Data.Function (on)
39−import Data.Hashable (hash)
4039import Data.List (deleteBy)
4140import Data.Maybe
4241#if MIN_VERSION_base(4,5,0)
@@ -57,9 +56,6 @@ import qualified Network.HTTP.Types.Header as H
5756import Network.Wai
5857import Network.Wai.Handler.Warp.Buffer (toBuilderBuffer)
5958import qualified Network.Wai.Handler.Warp.Date as D
60−#ifndef WINDOWS
61−import qualified Network.Wai.Handler.Warp.FdCache as F
62−#endif
6359import Network.Wai.Handler.Warp.File
6460import Network.Wai.Handler.Warp.Header
6561import Network.Wai.Handler.Warp.IO (toBufIOWith)
@@ -167,8 +163,8 @@ sendResponse settings conn ii req reqidxhdr src response = do
167163 hs0 = sanitizeHeaders $ responseHeaders response
168164 rspidxhdr = indexResponseHeader hs0
169165 th = threadHandle ii
170− dc = dateCacher ii
171− addServerAndDate = addDate dc rspidxhdr . addServer defServer rspidxhdr
166+ getdate = getDate ii
167+ addServerAndDate = addDate getdate rspidxhdr . addServer defServer rspidxhdr
172168 (isPersist,isChunked0) = infoFromRequest req reqidxhdr
173169 isChunked = not isHead && isChunked0
174170 (isKeepAlive, needsChunked) = infoFromResponse rspidxhdr (isPersist,isChunked)
@@ -294,9 +290,8 @@ sendRsp conn _ _ _ _ _ (RspRaw withApp src tickle) = do
294290-- Sophisticated WAI applications.
295291-- We respect s0. s0 MUST be a proper value.
296292sendRsp conn ii req ver s0 hs0 (RspFile path (Just part) _ isHead hook) =
297− sendRspFile2XX conn ii req ver s0 hs h path beg len isHead hook
293+ sendRspFile2XX conn ii req ver s0 hs path beg len isHead hook
298294 where
299− h = hash $ rawPathInfo req
300295 beg = filePartOffset part
301296 len = filePartByteCount part
302297 hs = addContentHeadersForFilePart hs0 part
@@ -306,8 +301,7 @@ sendRsp conn ii req ver s0 hs0 (RspFile path (Just part) _ isHead hook) =
306301-- Simple WAI applications.
307302-- Status is ignored
308303sendRsp conn ii req ver _ hs0 (RspFile path Nothing idxhdr isHead hook) = do
309− let h = hash $ rawPathInfo req
310− efinfo <- E.try $ fileInfo' ii h path
304+ efinfo <- E.try $ getFileInfo ii path
311305 case efinfo of
312306 Left (_ex :: E.IOException) ->
313307#ifdef WARP_DEBUG
@@ -316,7 +310,7 @@ sendRsp conn ii req ver _ hs0 (RspFile path Nothing idxhdr isHead hook) = do
316310 sendRspFile404 conn ii req ver hs0
317311 Right finfo -> case conditionalRequest finfo hs0 idxhdr of
318312 WithoutBody s -> sendRsp conn ii req ver s hs0 RspNoBody
319− WithBody s hs beg len -> sendRspFile2XX conn ii req ver s hs h path beg len isHead hook
313+ WithBody s hs beg len -> sendRspFile2XX conn ii req ver s hs path beg len isHead hook
320314
321315----------------------------------------------------------------
322316
@@ -326,29 +320,19 @@ sendRspFile2XX :: Connection
326320 -> H.HttpVersion
327321 -> H.Status
328322 -> H.ResponseHeaders
329− -> Hash
330323 -> FilePath
331324 -> Integer
332325 -> Integer
333326 -> Bool
334327 -> IO ()
335328 -> IO (Maybe H.Status, Maybe Integer)
336−sendRspFile2XX conn ii req ver s hs h path beg len isHead hook
329+sendRspFile2XX conn ii req ver s hs path beg len isHead hook
337330 | isHead = sendRsp conn ii req ver s hs RspNoBody
338331 | otherwise = do
339332 lheader <- composeHeader ver s hs
340−#ifdef WINDOWS
341− let fid = FileId path Nothing
342− hook' = hook
343−#else
344− (mfd, hook') <- case fdCacher ii of
345− -- settingsFdCacheDuration is 0
346− Nothing -> return (Nothing, hook)
347− Just fdc -> do
348− (fd, fresher) <- F.getFd' fdc h path
349− return (Just fd, hook >> fresher)
333+ (mfd, fresher) <- getFd ii path
350334 let fid = FileId path mfd
351−#endif
335+ hook' = hook >> fresher
352336 connSendFile conn fid beg len hook' [lheader]
353337 return (Just s, Just len)
354338
@@ -435,10 +419,10 @@ addTransferEncoding hdrs = (H.hTransferEncoding, "chunked") : hdrs
435419addTransferEncoding hdrs = ("transfer-encoding", "chunked") : hdrs
436420#endif
437421
438−addDate :: D.DateCache -> IndexedHeader -> H.ResponseHeaders -> IO H.ResponseHeaders
439−addDate dc rspidxhdr hdrs = case rspidxhdr ! fromEnum ResDate of
422+addDate :: IO D.GMTDate -> IndexedHeader -> H.ResponseHeaders -> IO H.ResponseHeaders
423+addDate getdate rspidxhdr hdrs = case rspidxhdr ! fromEnum ResDate of
440424 Nothing -> do
441− gmtdate <- D.getDate dc
425+ gmtdate <- getdate
442426 return $ (H.hDate, gmtdate) : hdrs
443427 Just _ -> return hdrs
444428
warp/Network/Wai/Handler/Warp/Run.hs+22−20
@@ -171,14 +171,14 @@ runSettingsConnectionMakerSecure :: Settings -> IO (IO (Connection, Transport),
171171runSettingsConnectionMakerSecure set getConnMaker app = do
172172 settingsBeforeMainLoop set
173173 counter <- newCounter
174− withII $ acceptConnection set getConnMaker app counter
174+ withII0 $ acceptConnection set getConnMaker app counter
175175 where
176− withII action =
176+ withII0 action =
177+ withTimeoutManager $ \tm ->
177178 D.withDateCache $ \dc ->
178− F.withFdCache fdCacheDurationInSeconds $ \fc ->
179− I.withFileInfoCache fdFileInfoDurationInSeconds $ \get get' ->
180− withTimeoutManager $ \tm -> do
181− let ii0 = InternalInfo undefined tm fc get get' dc -- fixme: undefined
179+ F.withFdCache fdCacheDurationInSeconds $ \fdc ->
180+ I.withFileInfoCache fdFileInfoDurationInSeconds $ \fic -> do
181+ let ii0 = InternalInfo0 tm dc fdc fic
182182 action ii0
183183
184184 fdCacheDurationInSeconds = settingsFdCacheDuration set * 1000000
@@ -207,7 +207,7 @@ acceptConnection :: Settings
207207 -> IO (IO (Connection, Transport), SockAddr)
208208 -> Application
209209 -> Counter
210− -> InternalInfo
210+ -> InternalInfo0
211211 -> IO ()
212212acceptConnection set getConnMaker app counter ii0 = do
213213 -- First mask all exceptions in acceptLoop. This is necessary to
@@ -257,7 +257,7 @@ fork :: Settings
257257 -> SockAddr
258258 -> Application
259259 -> Counter
260− -> InternalInfo
260+ -> InternalInfo0
261261 -> IO ()
262262fork set mkConn addr app counter ii0 = settingsFork set $ \ unmask ->
263263 -- Run the connection maker to get a new connection, and ensure
@@ -274,9 +274,9 @@ fork set mkConn addr app counter ii0 = settingsFork set $ \ unmask ->
274274
275275 -- We need to register a timeout handler for this thread, and
276276 -- cancel that handler as soon as we exit.
277− bracket (T.registerKillThread (timeoutManager ii0)) T.cancel $ \th ->
277+ bracket (T.registerKillThread (timeoutManager0 ii0)) T.cancel $ \th ->
278278
279− let ii = ii0 { threadHandle = th }
279+ let ii1 = toInternalInfo1 ii0 th
280280 -- We now have fully registered a connection close handler
281281 -- in the case of all exceptions, so it is safe to one
282282 -- again allow async exceptions.
@@ -290,7 +290,7 @@ fork set mkConn addr app counter ii0 = settingsFork set $ \ unmask ->
290290
291291 -- Actually serve this connection.
292292 -- bracket with closeConn above ensures the connection is closed.
293− when goingon $ serveConnection conn ii addr transport set app
293+ when goingon $ serveConnection conn ii1 addr transport set app
294294 where
295295 closeConn (conn, _transport) = connClose conn
296296
@@ -298,13 +298,13 @@ fork set mkConn addr app counter ii0 = settingsFork set $ \ unmask ->
298298 onClose adr _ = decrease counter >> settingsOnClose set adr
299299
300300serveConnection :: Connection
301− -> InternalInfo
301+ -> InternalInfo1
302302 -> SockAddr
303303 -> Transport
304304 -> Settings
305305 -> Application
306306 -> IO ()
307−serveConnection conn ii origAddr transport settings app = do
307+serveConnection conn ii1 origAddr transport settings app = do
308308 -- fixme: Upgrading to HTTP/2 should be supported.
309309 (h2,bs) <- if isHTTP2 transport then
310310 return (True, "")
@@ -317,7 +317,7 @@ serveConnection conn ii origAddr transport settings app = do
317317 if settingsHTTP2Enabled settings && h2 then do
318318 recvN <- makeReceiveN bs (connRecv conn) (connRecvBuf conn)
319319 -- fixme: origAddr
320− http2 conn ii origAddr transport settings recvN app
320+ http2 conn ii1 origAddr transport settings recvN app
321321 else do
322322 istatus <- newIORef False
323323 src <- mkSource (wrappedRecv conn th istatus (settingsSlowlorisSize settings))
@@ -368,7 +368,7 @@ serveConnection conn ii origAddr transport settings app = do
368368
369369 decodeAscii = map (chr . fromEnum) . S.unpack
370370
371− th = threadHandle ii
371+ th = threadHandle1 ii1
372372
373373 shouldSendErrorResponse se
374374 | Just ConnectionClosedByPeer <- fromException se = False
@@ -376,17 +376,19 @@ serveConnection conn ii origAddr transport settings app = do
376376
377377 sendErrorResponse addr istatus e = do
378378 status <- readIORef istatus
379− when (shouldSendErrorResponse e && status) $ void $
380− sendResponse settings conn ii (dummyreq addr) defaultIndexRequestHeader (return S.empty) (errorResponse e)
379+ when (shouldSendErrorResponse e && status) $ do
380+ let ii = toInternalInfo ii1 0 -- dummy
381+ dreq = dummyreq addr
382+ void $ sendResponse settings conn ii dreq defaultIndexRequestHeader (return S.empty) (errorResponse e)
381383
382384 dummyreq addr = defaultRequest { remoteHost = addr }
383385
384386 errorResponse e = settingsOnExceptionResponse settings e
385387
386388 http1 addr istatus src = do
387− (req', mremainingRef, idxhdr, nextBodyFlush) <- recvRequest settings conn ii addr src
389+ (req', mremainingRef, idxhdr, nextBodyFlush, ii) <- recvRequest settings conn ii1 addr src
388390 let req = req' { isSecure = isTransportSecure transport }
389− keepAlive <- processRequest istatus src req mremainingRef idxhdr nextBodyFlush
391+ keepAlive <- processRequest istatus src req mremainingRef idxhdr nextBodyFlush ii
390392 `E.catch` \e -> do
391393 -- Call the user-supplied exception handlers, passing the request.
392394 sendErrorResponse addr istatus e
@@ -395,7 +397,7 @@ serveConnection conn ii origAddr transport settings app = do
395397 return False
396398 when keepAlive $ http1 addr istatus src
397399
398− processRequest istatus src req mremainingRef idxhdr nextBodyFlush = do
400+ processRequest istatus src req mremainingRef idxhdr nextBodyFlush ii = do
399401 -- Let the application run for as long as it wants
400402 T.pause th
401403
warp/Network/Wai/Handler/Warp/SendFile.hs+3−3
@@ -30,7 +30,7 @@ import Foreign.C.Error (throwErrno)
3030import Foreign.C.Types
3131import Foreign.Ptr (Ptr, castPtr, plusPtr)
3232import Network.Sendfile
33−import System.Posix.IO (openFd, OpenFileFlags(..), defaultFileFlags, OpenMode(ReadOnly), closeFd)
33+import Network.Wai.Handler.Warp.FdCache (openFile, closeFile)
3434import System.Posix.Types
3535#endif
3636
@@ -129,10 +129,10 @@ readSendFile buf siz send fid off0 len0 hook headers =
129129 path = fileIdPath fid
130130 setup = case fileIdFd fid of
131131 Just fd -> return fd
132− Nothing -> openFd path ReadOnly Nothing defaultFileFlags{nonBlock=True}
132+ Nothing -> openFile path
133133 teardown fd = case fileIdFd fid of
134134 Just _ -> return ()
135− Nothing -> closeFd fd
135+ Nothing -> closeFile fd
136136 loop fd len off
137137 | len <= 0 = return ()
138138 | otherwise = do
warp/Network/Wai/Handler/Warp/Types.hs+30−6
@@ -116,16 +116,40 @@ data Connection = Connection {
116116
117117type Hash = Int
118118
119−-- | Internal information.
119+
120+data InternalInfo0 =
121+ InternalInfo0 T.Manager
122+ (IO D.GMTDate)
123+ (Hash -> FilePath -> IO (Maybe F.Fd, F.Refresh))
124+ (Hash -> FilePath -> IO I.FileInfo)
125+
126+timeoutManager0 :: InternalInfo0 -> T.Manager
127+timeoutManager0 (InternalInfo0 tm _ _ _) = tm
128+
129+data InternalInfo1 =
130+ InternalInfo1 T.Handle
131+ T.Manager
132+ (IO D.GMTDate)
133+ (Hash -> FilePath -> IO (Maybe F.Fd, F.Refresh))
134+ (Hash -> FilePath -> IO I.FileInfo)
135+
136+toInternalInfo1 :: InternalInfo0 -> T.Handle -> InternalInfo1
137+toInternalInfo1 (InternalInfo0 b c d e) a = InternalInfo1 a b c d e
138+
139+threadHandle1 :: InternalInfo1 -> T.Handle
140+threadHandle1 (InternalInfo1 th _ _ _ _) = th
141+
120142data InternalInfo = InternalInfo {
121− threadHandle :: T.Handle
143+ threadHandle :: T.Handle
122144 , timeoutManager :: T.Manager
123− , fdCacher :: Maybe F.MutableFdCache
124− , fileInfo :: FilePath -> IO I.FileInfo
125− , fileInfo' :: Int -> FilePath -> IO I.FileInfo
126− , dateCacher :: D.DateCache
145+ , getDate :: IO D.GMTDate
146+ , getFd :: FilePath -> IO (Maybe F.Fd, F.Refresh)
147+ , getFileInfo :: FilePath -> IO I.FileInfo
127148 }
128149
150+toInternalInfo :: InternalInfo1 -> Hash -> InternalInfo
151+toInternalInfo (InternalInfo1 a b c d e) h = InternalInfo a b c (d h) (e h)
152+
129153----------------------------------------------------------------
130154
131155-- | Type for input streaming.
warp/test/FdCacheSpec.hs+2−2
@@ -16,8 +16,8 @@ spec :: Spec
1616spec = describe "withFdCache" $ do
1717 it "clean up Fd" $ do
1818 ref <- newIORef (Fd (-1))
19− withFdCache 30000000 $ \(Just mfc) -> do
20− (fd,_) <- getFd mfc "warp.cabal"
19+ withFdCache 30000000 $ \getFd -> do
20+ (Just fd,_) <- getFd 0 "warp.cabal"
2121 writeIORef ref fd
2222 nfd <- readIORef ref
2323 fdRead nfd 1 `shouldThrow` anyIOException