@@ -6,10 +6,12 @@ module Network.Wai.Handler.Warp.SendFile (
66 , packHeader -- for testing
77 ) where
88
9+import Control.Monad (void)
10+import qualified Data.ByteString as BS
911import Data.ByteString.Internal
10−import Foreign.ForeignPtr (newForeignPtr_, withForeignPtr)
1112import Network.Sendfile
1213import Network.Socket (Socket)
14+import Network.Wai.Handler.Warp.Buffer
1315import Network.Wai.Handler.Warp.Types
1416
1517#ifdef WINDOWS
@@ -50,23 +52,21 @@ packHeader :: Buffer -> BufSize -> (ByteString -> IO ())
5052 -> Int
5153 -> IO Int
5254packHeader _ _ _ _ [] n = return n
53−packHeader buf siz send hook (PS bsfp off len : bss) n
54− | len < room = withForeignPtr bsfp $ \bsp -> do
55+packHeader buf siz send hook (bs:bss) n
56+ | len < room = do
5557 let dst = buf `plusPtr` n
56− src = bsp `plusPtr` off
57− memcpy dst src len
58+ void $ copy dst bs
5859 packHeader buf siz send hook bss (n + len)
59− | otherwise = withForeignPtr bsfp $ \bsp -> do
60+ | otherwise = do
6061 let dst = buf `plusPtr` n
61− src = bsp `plusPtr` off
62− memcpy dst src room
63− fptr <- newForeignPtr_ buf
64− let entire = PS fptr 0 siz
65− bs = PS bsfp (off + room) (len - room)
62+ (bs1, bs2) = BS.splitAt room bs
63+ void $ copy dst bs1
64+ entire <- toBS buf siz
6665 send entire
6766 hook
68− packHeader buf siz send hook (bs:bss) 0
67+ packHeader buf siz send hook (bs2:bss) 0
6968 where
69+ len = BS.length bs
7070 room = siz - n
7171
7272mini :: Int -> Integer -> Int
@@ -77,15 +77,14 @@ mini i n
7777#ifdef WINDOWS
7878readSendFile :: Buffer -> BufSize -> (ByteString -> IO ()) -> SendFile
7979readSendFile buf siz send fid off0 len0 hook headers = do
80− fptr <- newForeignPtr_ buf
8180 hn <- packHeader buf siz send hook headers 0
8281 let room = siz - hn
8382 buf' = buf `plusPtr` hn
8483 IO.withBinaryFile path IO.ReadMode $ \h -> do
8584 IO.hSeek h IO.AbsoluteSeek off0
8685 n <- IO.hGetBufSome h buf' (mini room len0)
87− let bs = PS fptr 0 (hn + n)
88− n' = fromIntegral n
86+ bs <- toBSD buf (hn + n)
87+ let n' = fromIntegral n
8988 send bs
9089 hook
9190 loop h fptr (len0 - n')
@@ -105,16 +104,15 @@ readSendFile buf siz send fid off0 len0 hook headers = do
105104readSendFile :: Buffer -> BufSize -> (ByteString -> IO ()) -> SendFile
106105readSendFile buf siz send fid off0 len0 hook headers =
107106 bracket setup teardown $ \fd -> do
108− fptr <- newForeignPtr_ buf
109107 hn <- packHeader buf siz send hook headers 0
110108 let room = siz - hn
111109 buf' = buf `plusPtr` hn
112110 n <- positionRead fd buf' (mini room len0) off0
113− let bs = PS fptr 0 (hn + n)
114− n' = fromIntegral n
111+ bs <- toBS buf (hn + n)
112+ let n' = fromIntegral n
115113 send bs
116114 hook
117− loop fd fptr (len0 - n') (off0 + n')
115+ loop fd (len0 - n') (off0 + n')
118116 where
119117 path = fileIdPath fid
120118 setup = case fileIdFd fid of
@@ -123,15 +121,15 @@ readSendFile buf siz send fid off0 len0 hook headers =
123121 teardown fd = case fileIdFd fid of
124122 Just _ -> return ()
125123 Nothing -> closeFd fd
126− loop fd fptr len off
124+ loop fd len off
127125 | len <= 0 = return ()
128126 | otherwise = do
129127 n <- positionRead fd buf (mini siz len) off
130− let bs = PS fptr 0 n
131− n' = fromIntegral n
128+ bs <- toBS buf n
129+ let n' = fromIntegral n
132130 send bs
133131 hook
134− loop fd fptr (len - n') (off + n')
132+ loop fd (len - n') (off + n')
135133
136134positionRead :: Fd -> Ptr Word8 -> Int -> Integer -> IO Int
137135positionRead (Fd fd) buf siz off =