diff options
Diffstat (limited to 'lib/unicorn/socket_helper.rb')
-rw-r--r-- | lib/unicorn/socket_helper.rb | 74 |
1 files changed, 44 insertions, 30 deletions
diff --git a/lib/unicorn/socket_helper.rb b/lib/unicorn/socket_helper.rb index 1d03eab..9f2d55c 100644 --- a/lib/unicorn/socket_helper.rb +++ b/lib/unicorn/socket_helper.rb @@ -17,9 +17,16 @@ module Unicorn # denial-of-service attacks :tcp_defer_accept => 1, - # FreeBSD, we need to override this to 'dataready' when we + # FreeBSD, we need to override this to 'dataready' if we # eventually get HTTPS support :accept_filter => 'httpready', + + # same default value as Mongrel + :backlog => 1024, + + # since we don't do keepalive, we'll always flush-on-close and + # this saves packets for everyone. + :tcp_nopush => true, } #:startdoc: @@ -41,19 +48,20 @@ module Unicorn end def set_tcp_sockopt(sock, opt) - # highly portable, but off by default because we don't do keepalive - if defined?(TCP_NODELAY) && ! (val = opt[:tcp_nodelay]).nil? + if defined?(TCP_NODELAY) + val = opt[:tcp_nodelay] + val = DEFAULTS[:tcp_nodelay] if nil == val sock.setsockopt(IPPROTO_TCP, TCP_NODELAY, val ? 1 : 0) end - unless (val = opt[:tcp_nopush]).nil? - val = val ? 1 : 0 - if defined?(TCP_CORK) # Linux - sock.setsockopt(IPPROTO_TCP, TCP_CORK, val) - elsif defined?(TCP_NOPUSH) # TCP_NOPUSH is untested (FreeBSD) - sock.setsockopt(IPPROTO_TCP, TCP_NOPUSH, val) - end + val = opt[:tcp_nopush] + val = DEFAULTS[:tcp_nopush] if nil == val + val = val ? 1 : 0 + if defined?(TCP_CORK) # Linux + sock.setsockopt(IPPROTO_TCP, TCP_CORK, val) + elsif defined?(TCP_NOPUSH) # TCP_NOPUSH is untested (FreeBSD) + sock.setsockopt(IPPROTO_TCP, TCP_NOPUSH, val) end # No good reason to ever have deferred accepts off @@ -61,26 +69,24 @@ module Unicorn if defined?(TCP_DEFER_ACCEPT) # this differs from nginx, since nginx doesn't allow us to # configure the the timeout... - tmp = DEFAULTS.merge(opt) - seconds = tmp[:tcp_defer_accept] - seconds = DEFAULTS[:tcp_defer_accept] if seconds == true + seconds = opt[:tcp_defer_accept] + seconds = DEFAULTS[:tcp_defer_accept] if [true,nil].include?(seconds) seconds = 0 unless seconds # nil/false means disable this sock.setsockopt(SOL_TCP, TCP_DEFER_ACCEPT, seconds) elsif respond_to?(:accf_arg) - tmp = DEFAULTS.merge(opt) - if name = tmp[:accept_filter] - begin - sock.setsockopt(SOL_SOCKET, SO_ACCEPTFILTER, accf_arg(name)) - rescue => e - logger.error("#{sock_name(sock)} " \ - "failed to set accept_filter=#{name} (#{e.inspect})") - end + name = opt[:accept_filter] + name = DEFAULTS[:accept_filter] if nil == name + begin + sock.setsockopt(SOL_SOCKET, SO_ACCEPTFILTER, accf_arg(name)) + rescue => e + logger.error("#{sock_name(sock)} " \ + "failed to set accept_filter=#{name} (#{e.inspect})") end end end def set_server_sockopt(sock, opt) - opt ||= {} + opt = DEFAULTS.merge(opt || {}) TCPSocket === sock and set_tcp_sockopt(sock, opt) @@ -90,7 +96,7 @@ module Unicorn sock.setsockopt(SOL_SOCKET, SO_SNDBUF, opt[:sndbuf]) if opt[:sndbuf] log_buffer_sizes(sock, " after: ") end - sock.listen(opt[:backlog] || 1024) + sock.listen(opt[:backlog]) rescue => e logger.error "error setting socket options: #{e.inspect}" logger.error e.backtrace.join("\n") @@ -126,12 +132,13 @@ module Unicorn end old_umask = File.umask(opt[:umask] || 0) begin - UNIXServer.new(address) + Kgio::UNIXServer.new(address) ensure File.umask(old_umask) end - elsif address =~ /^(\d+\.\d+\.\d+\.\d+):(\d+)$/ - TCPServer.new($1, $2.to_i) + elsif /\A(\d+\.\d+\.\d+\.\d+):(\d+)\z/ =~ address || + /\A\[([a-fA-F0-9:]+)\]:(\d+)\z/ =~ address + Kgio::TCPServer.new($1, $2.to_i) else raise ArgumentError, "Don't know how to bind: #{address}" end @@ -139,6 +146,13 @@ module Unicorn sock end + # returns rfc2732-style (e.g. "[::1]:666") addresses for IPv6 + def tcp_name(sock) + port, addr = Socket.unpack_sockaddr_in(sock.getsockname) + /:/ =~ addr ? "[#{addr}]:#{port}" : "#{addr}:#{port}" + end + module_function :tcp_name + # Returns the configuration name of a socket as a string. sock may # be a string value, in which case it is returned as-is # Warning: TCP sockets may not always return the name given to it. @@ -148,10 +162,10 @@ module Unicorn when UNIXServer Socket.unpack_sockaddr_un(sock.getsockname) when TCPServer - Socket.unpack_sockaddr_in(sock.getsockname).reverse!.join(':') + tcp_name(sock) when Socket begin - Socket.unpack_sockaddr_in(sock.getsockname).reverse!.join(':') + tcp_name(sock) rescue ArgumentError Socket.unpack_sockaddr_un(sock.getsockname) end @@ -166,9 +180,9 @@ module Unicorn def server_cast(sock) begin Socket.unpack_sockaddr_in(sock.getsockname) - TCPServer.for_fd(sock.fileno) + Kgio::TCPServer.for_fd(sock.fileno) rescue ArgumentError - UNIXServer.for_fd(sock.fileno) + Kgio::UNIXServer.for_fd(sock.fileno) end end |