moonbridge

changeset 202:2ed3d94a0eb7

Improvements to timeout system of HTTP module
author jbe
date Sun Jun 21 02:05:24 2015 +0200 (2015-06-21)
parents 4e72725118d0
children a1907691f740
files moonbridge_http.lua
line diff
     1.1 --- a/moonbridge_http.lua	Sat Jun 20 02:33:40 2015 +0200
     1.2 +++ b/moonbridge_http.lua	Sun Jun 21 02:05:24 2015 +0200
     1.3 @@ -197,9 +197,10 @@
     1.4    local output_chunk_size = options.minimum_output_chunk_size or options.chunk_size or 1024
     1.5    local header_size_limit = options.header_size_limit or 1024*1024
     1.6    local body_size_limit   = options.body_size_limit   or 64*1024*1024
     1.7 -  local request_idle_timeout   = default("request_idle_timeout", 65)
     1.8 -  local request_header_timeout = default("request_header_timeout", 30)
     1.9 -  local response_timeout       = default("response_timeout", 1800)
    1.10 +  local idle_timeout           = default("idle_timeout", 65)
    1.11 +  local stall_timeout          = default("stall_timeout", 60)
    1.12 +  local request_header_timeout = default("request_header_timeout", 120)
    1.13 +  local response_timeout       = default("response_timeout", 3600)
    1.14    local drain_timeout          = default("drain_timeout", 2)
    1.15    local poll = options.poll_function or moonbridge_io.poll
    1.16    -- return socket handler:
    1.17 @@ -218,28 +219,31 @@
    1.18      -- function trying to unblock socket by reading:
    1.19      local function unblock()
    1.20        if consume then
    1.21 -        poll(socket_set, socket_set)
    1.22 +        if not poll(socket_set, socket_set, stall_timeout) then
    1.23 +          socket:reset()
    1.24 +          error("Client connection stalled")
    1.25 +        end
    1.26          consume()
    1.27        else
    1.28 -        poll(nil, socket_set)
    1.29 +        if not poll(nil, socket_set, stall_timeout) then
    1.30 +          socket:reset()
    1.31 +          error("Client connection stalled")
    1.32 +        end
    1.33        end
    1.34      end
    1.35      -- function that enforces consumption of all input:
    1.36 -    local function consume_all()
    1.37 -      local endtime
    1.38 -      if consume == drain then
    1.39 -        -- do not consume endlessly for the sole purpose to drain
    1.40 -        endtime = moonbridge_io.timeref() + drain_timeout
    1.41 -      end
    1.42 +    local function consume_all(timeout)
    1.43 +      local starttime = timeout and moonbridge_io.timeref()
    1.44        while consume do
    1.45 -        if endtime then
    1.46 -          if not poll(socket_set, nil, 0-moonbridge_io.timeref(endtime)) then
    1.47 -            break
    1.48 +        if timeout then
    1.49 +          if not poll(socket_set, nil, timeout-moonbridge_io.timeref(starttime)) then
    1.50 +            return false
    1.51            end
    1.52          else
    1.53            poll(socket_set, nil)
    1.54          end
    1.55          consume()
    1.56 +        return true
    1.57        end
    1.58      end
    1.59      -- handle requests in a loop:
    1.60 @@ -407,9 +411,13 @@
    1.61            send_flush()
    1.62            assert_close(socket:finish())
    1.63            -- wait for EOF from peer to avoid immediate TCP RST condition:
    1.64 -          consume_all()
    1.65 -          -- fully close socket:
    1.66 -          assert_close(socket:close())
    1.67 +          if consume_all(drain_timeout) then
    1.68 +            -- fully close socket:
    1.69 +            assert_close(socket:close())
    1.70 +          else
    1.71 +            -- send TCP RST if draining input takes too long:
    1.72 +            assert_close(socket:reset())
    1.73 +          end
    1.74          else
    1.75            -- flush outgoing data:
    1.76            send_flush()
    1.77 @@ -1071,7 +1079,7 @@
    1.78          return true  -- success
    1.79        end
    1.80        -- wait for input:
    1.81 -      if not poll(socket_set, nil, request_idle_timeout) then
    1.82 +      if not poll(socket_set, nil, idle_timeout) then
    1.83          return request_error(false, "408 Request Timeout", "Idle connection timed out")
    1.84        end
    1.85        -- read headers (with timeout):
    1.86 @@ -1081,11 +1089,16 @@
    1.87          while true do
    1.88            local status, retval = coro()
    1.89            if status == nil then
    1.90 -            local remaining
    1.91 +            local timeout
    1.92              if request_header_timeout then
    1.93 -              remaining = request_header_timeout - moonbridge_io.timeref(starttime)
    1.94 +              timeout = request_header_timeout - moonbridge_io.timeref(starttime)
    1.95 +              if stall_timeout and timeout > stall_timeout then
    1.96 +                timeout = stall_timeout
    1.97 +              end
    1.98 +            else
    1.99 +              timeout = stall_timeout
   1.100              end
   1.101 -            if not poll(socket_set, nil, remaining) then
   1.102 +            if not poll(socket_set, nil, timeout) then
   1.103                return request_error(false, "408 Request Timeout", "Timeout while receiving headers")
   1.104              end
   1.105            elseif status == false then

Impressum / About Us