on master help sign in
Optional timeout protection
commit3745201aed70828a5cfeacbc55d09954c8a99e77 authorMichael Snoyman <michael@snoyman.com> dateThu 30 Dec 2010, 23:49 (16 years ago) parent5513470
2 files changed+29−5
Network/Wai/Handler/Warp.hs+17−4 warp.cabal+12−1
Network/Wai/Handler/Warp.hs+17−4
@@ -1,6 +1,7 @@
11{-# LANGUAGE DeriveDataTypeable #-}
22{-# LANGUAGE FlexibleContexts #-}
33{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE CPP #-}
45---------------------------------------------------------
56-- |
67-- Module : Network.Wai.Handler.Warp
@@ -58,6 +59,7 @@ import Data.Monoid (mconcat)
5859import Network.Socket.SendFile (sendFile)
5960
6061import Control.Monad.IO.Class (liftIO)
62+import System.Timeout (timeout)
6163
6264run :: Port -> Application -> IO ()
6365run port = withSocketsDo .
@@ -102,10 +104,11 @@ parseRequest port remoteHost' = do
102104 parseRequest' port headers' remoteHost'
103105
104106-- FIXME come up with good values here
105−maxHeaders, maxHeaderLength, bytesPerRead :: Int
107+maxHeaders, maxHeaderLength, bytesPerRead, readTimeout :: Int
106108maxHeaders = 30
107109maxHeaderLength = 1024
108110bytesPerRead = 4096
111+readTimeout = 3000000
109112
110113takeUntilBlank :: Int
111114 -> ([ByteString] -> [ByteString])
@@ -146,6 +149,7 @@ data InvalidRequest =
146149 | TooManyHeaders
147150 | IncompleteHeaders
148151 | OverLargeHeader
152+ | SocketTimeout
149153 deriving (Show, Typeable)
150154instance Exception InvalidRequest
151155
@@ -310,8 +314,17 @@ iterSocket socket =
310314 go (E.Chunks cs) = liftIO (Sock.sendMany socket cs) >> E.continue go
311315
312316enumSocket len socket (E.Continue k) = do
317+#if NO_TIMEOUT_PROTECTION
313318 bs <- liftIO $ Sock.recv socket len
314− if S.length bs == 0
315− then E.continue k
316− else k (E.Chunks [bs]) >>== enumSocket len socket
319+ go bs
320+#else
321+ mbs <- liftIO $ timeout readTimeout $ Sock.recv socket len
322+ case mbs of
323+ Nothing -> E.throwError SocketTimeout
324+ Just bs -> go bs
325+#endif
326+ where
327+ go bs
328+ | S.length bs == 0 = E.continue k
329+ | otherwise = k (E.Chunks [bs]) >>== enumSocket len socket
317330enumSocket _ _ step = E.returnI step
warp.cabal+12−1
@@ -11,18 +11,29 @@ Build-Type: Simple
1111Cabal-Version: >=1.6
1212Stability: Stable
1313
14+flag timeout-protection
15+ Description: Use timeouts (very performance-costly) to protect against DOS attacks.
16+ Default: True
17+flag network-bytestring
18+
1419Library
1520 Build-Depends: base >= 3 && < 5
1621 , bytestring >= 0.9 && < 0.10
1722 , wai >= 0.3.0 && < 0.4
18− , network >= 2.3 && < 2.4
1923 , blaze-builder-enumerator >= 0.2 && < 0.3
2024 , transformers >= 0.2 && < 0.3
2125 , enumerator >= 0.4 && < 0.5
2226 , blaze-builder >= 0.2.1.3 && < 0.3
2327 , sendfile >= 0.7.2 && < 0.8
28+ if flag(network-bytestring)
29+ build-depends: network >= 2.2.1 && < 2.2.3
30+ , network-bytestring >= 0.1.3 && < 0.1.4
31+ else
32+ build-depends: network >= 2.3 && < 2.4
2433 Exposed-modules: Network.Wai.Handler.Warp
2534 ghc-options: -Wall
35+ if !flag(timeout-protection)
36+ Cpp-options: -DNO_TIMEOUT_PROTECTION
2637
2738Executable warp
2839 Main-is: warp.hs