moonbridge

changeset 115:7014436d88ea

Added helper function moonbridge_io.timeref(...); HTTP module sends 408 Request Timeout
author jbe
date Fri Apr 10 00:33:07 2015 +0200 (2015-04-10)
parents 0eba766e9be2
children 2ab19e15aa6b
files example_application.lua moonbridge.c moonbridge_http.lua moonbridge_io.c
line diff
     1.1 --- a/example_application.lua	Thu Apr 09 20:02:43 2015 +0200
     1.2 +++ b/example_application.lua	Fri Apr 10 00:33:07 2015 +0200
     1.3 @@ -60,7 +60,8 @@
     1.4      {
     1.5        static_headers = {"Server: Moonbridge Example Server"},
     1.6        request_body_size_limit = 16*1024*1024*1024,  -- allow big file uploads
     1.7 -      request_header_timeout = 360,  -- request headers must be sent within 6 minutes (if nil, defaults to timeout below)
     1.8 +      request_idle_timeout = 330,  -- 5 minutes and 30 seconds after which an idle connection will be closed
     1.9 +      request_header_timeout = 30,  -- request headers must be sent within 30 seconds after first byte was received
    1.10        timeout = 1800  -- request body and response must be sent within 30 minutes
    1.11      },
    1.12      function(request)
     2.1 --- a/moonbridge.c	Thu Apr 09 20:02:43 2015 +0200
     2.2 +++ b/moonbridge.c	Fri Apr 10 00:33:07 2015 +0200
     2.3 @@ -2016,7 +2016,7 @@
     2.4        return lua_gettop(L) - 1;
     2.5      }
     2.6    }
     2.7 -  lua_pushnumber(L, oldval.it_value.tv_sec + 1e-6 * oldval.it_value.tv_usec); 
     2.8 +  lua_pushnumber(L, oldval.it_value.tv_sec + 1e-6 * oldval.it_value.tv_usec);
     2.9    return 1;
    2.10  }
    2.11  
     3.1 --- a/moonbridge_http.lua	Thu Apr 09 20:02:43 2015 +0200
     3.2 +++ b/moonbridge_http.lua	Fri Apr 10 00:33:07 2015 +0200
     3.3 @@ -180,13 +180,16 @@
     3.4    end
     3.5    local input_chunk_size = options.maximum_input_chunk_size or options.chunk_size or 16384
     3.6    local output_chunk_size = options.minimum_output_chunk_size or options.chunk_size or 1024
     3.7 -  local request_header_timeout, response_timeout
     3.8 +  local request_idle_timeout, request_header_timeout, response_timeout
     3.9 +  if options.request_idle_timeout ~= nil then
    3.10 +    request_idle_timeout = options.request_idle_timeout or 0
    3.11 +  else
    3.12 +    request_idle_timeout = 330
    3.13 +  end
    3.14    if options.request_header_timeout ~= nil then
    3.15 -    request_header_timeout = options.request_header_timeout
    3.16 -  elseif options.timeout ~= nil then
    3.17 -    request_header_timeout = options.timeout or 0
    3.18 +    request_header_timeout = options.request_header_timeout or 0
    3.19    else
    3.20 -    request_header_timeout = 360
    3.21 +    request_header_timeout = 30
    3.22    end
    3.23    if options.timeout ~= nil then
    3.24      response_timeout = options.timeout or 0
    3.25 @@ -195,10 +198,9 @@
    3.26    end
    3.27    -- return connect handler:
    3.28    return function(socket)
    3.29 +    local socket_set = {[socket] = true}  -- used for moonbridge_io.poll(...)
    3.30      local survive = true  -- set to false if process shall be terminated later
    3.31      repeat
    3.32 -      -- (re)set timeout:
    3.33 -      timeout(request_header_timeout or 0)
    3.34        -- process named arguments "request_header_size_limit" and "request_body_size_limit":
    3.35        local remaining_header_size_limit = options.request_header_size_limit or 1024*1024
    3.36        local remaining_body_size_limit = options.request_body_size_limit or 64*1024*1024
    3.37 @@ -311,9 +313,13 @@
    3.38            -- close output stream:
    3.39            assert_output(socket:finish())
    3.40            -- wait for EOF of peer to avoid immediate TCP RST condition:
    3.41 -          timeout(2, function()
    3.42 -            socket:drain()
    3.43 -          end)
    3.44 +          do
    3.45 +            local start_time = moonbridge_io.timeref()
    3.46 +            repeat
    3.47 +              socket:drain_nb()
    3.48 +              local time_left = 2 - moonbridge_io.timeref(start_time)
    3.49 +            until time_left <= 0 or not moonbridge_io.poll(socket_set, nil, time_left)
    3.50 +          end
    3.51            -- fully close socket:
    3.52            socket_closed = true  -- avoid double close on error
    3.53            assert_output(socket:close())
    3.54 @@ -893,6 +899,12 @@
    3.55            end
    3.56          end
    3.57        })
    3.58 +      -- wait for input:
    3.59 +      if not moonbridge_io.poll({[socket] = true}, nil, request_idle_timeout) then
    3.60 +        return request_error(false, "408 Request Timeout")
    3.61 +      end
    3.62 +      -- set timeout for request header processing:
    3.63 +      timeout(request_header_timeout)
    3.64        -- read and parse request line:
    3.65        local line = socket:read(remaining_header_size_limit, "\n")
    3.66        if not line then return survive end
    3.67 @@ -991,12 +1003,14 @@
    3.68            request.cookies[decode_uri(rawkey)] = decode_uri(rawvalue)
    3.69          end
    3.70        end
    3.71 -      -- (re)set timeout:
    3.72 +      -- (re)set timeout for handler:
    3.73        timeout(response_timeout or 0)
    3.74        -- call underlying handler and remember boolean result:
    3.75        if handler(request) ~= true then survive = false end
    3.76        -- finish request (unless already done by underlying handler):
    3.77        request:finish()
    3.78 +      -- stop timeout timer:
    3.79 +      timeout(0)
    3.80      until connection_close_responded
    3.81      return survive
    3.82    end
     4.1 --- a/moonbridge_io.c	Thu Apr 09 20:02:43 2015 +0200
     4.2 +++ b/moonbridge_io.c	Fri Apr 10 00:33:07 2015 +0200
     4.3 @@ -14,6 +14,7 @@
     4.4  #include <sys/types.h>
     4.5  #include <netdb.h>
     4.6  #include <signal.h>
     4.7 +#include <time.h>
     4.8  
     4.9  #include <lua.h>
    4.10  #include <lauxlib.h>
    4.11 @@ -1026,6 +1027,17 @@
    4.12    }
    4.13  }
    4.14  
    4.15 +static int moonbr_io_timeref(lua_State *L) {
    4.16 +  lua_Number sub;
    4.17 +  struct timespec tp;
    4.18 +  sub = luaL_optnumber(L, 1, 0);
    4.19 +  if (clock_gettime(CLOCK_MONOTONIC, &tp)) {
    4.20 +    return luaL_error(L, "Could not access CLOCK_MONOTONIC");
    4.21 +  }
    4.22 +  lua_pushnumber(L, tp.tv_sec + tp.tv_nsec / 1.0e9 - sub);
    4.23 +  return 1;
    4.24 +}
    4.25 +
    4.26  static const struct luaL_Reg moonbr_io_handle_methods[] = {
    4.27    {"read", moonbr_io_read},
    4.28    {"read_nb", moonbr_io_read_nb},
    4.29 @@ -1068,6 +1080,7 @@
    4.30    {"locallisten", moonbr_io_locallisten},
    4.31    {"tcplisten", moonbr_io_tcplisten},
    4.32    {"poll", moonbr_io_poll},
    4.33 +  {"timeref", moonbr_io_timeref},
    4.34    {NULL, NULL}
    4.35  };
    4.36  

Impressum / About Us