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