from /usr/include/linux/tcp.h
The semantics for TCP_DEFER_ACCEPT changed in Linux 2.6.32+ with commit d1b99ba41d6c5aa1ed2fc634323449dd656899e9 This change shouldn’t affect Unicorn users behind nginx (a value of 1 remains an optimization), but Rainbows! users may want to use a higher value on Linux 2.6.32+ to protect against denial-of-service attacks
do not send out partial frames (Linux)
do not send out partial frames (FreeBSD)
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.
# File lib/unicorn/socket_helper.rb, line 143
143: def sock_name(sock)
144: case sock
145: when String then sock
146: when UNIXServer
147: Socket.unpack_sockaddr_un(sock.getsockname)
148: when TCPServer
149: Socket.unpack_sockaddr_in(sock.getsockname).reverse!.join(':')
150: when Socket
151: begin
152: Socket.unpack_sockaddr_in(sock.getsockname).reverse!.join(':')
153: rescue ArgumentError
154: Socket.unpack_sockaddr_un(sock.getsockname)
155: end
156: else
157: raise ArgumentError, "Unhandled class #{sock.class}: #{sock.inspect}"
158: end
159: end
struct accept_filter_arg {
char af_name[16]; char af_arg[240];
};
af_name is either “httpready” or “dataready”, though other filters may be supported by FreeBSD
# File lib/unicorn/socket_helper.rb, line 43
43: def accf_arg(af_name)
44: [ af_name, nil ].pack('a16a240')
45: end
creates a new server, socket. address may be a HOST:PORT or an absolute path to a UNIX socket. address can even be a Socket object in which case it is immediately returned
# File lib/unicorn/socket_helper.rb, line 110
110: def bind_listen(address = '0.0.0.0:8080', opt = {})
111: return address unless String === address
112:
113: sock = if address[0] == //
114: if File.exist?(address)
115: if File.socket?(address)
116: if self.respond_to?(:logger)
117: logger.info "unlinking existing socket=#{address}"
118: end
119: File.unlink(address)
120: else
121: raise ArgumentError,
122: "socket=#{address} specified but it is not a socket!"
123: end
124: end
125: old_umask = File.umask(opt[:umask] || 0)
126: begin
127: UNIXServer.new(address)
128: ensure
129: File.umask(old_umask)
130: end
131: elsif address =~ /^(\d+\.\d+\.\d+\.\d+):(\d+)$/
132: TCPServer.new($1, $2.to_i)
133: else
134: raise ArgumentError, "Don't know how to bind: #{address}"
135: end
136: set_server_sockopt(sock, opt)
137: sock
138: end
# File lib/unicorn/socket_helper.rb, line 100
100: def log_buffer_sizes(sock, pfx = '')
101: respond_to?(:logger) or return
102: rcvbuf = sock.getsockopt(SOL_SOCKET, SO_RCVBUF).unpack('i')
103: sndbuf = sock.getsockopt(SOL_SOCKET, SO_SNDBUF).unpack('i')
104: logger.info "#{pfx}#{sock_name(sock)} rcvbuf=#{rcvbuf} sndbuf=#{sndbuf}"
105: end
casts a given Socket to be a TCPServer or UNIXServer
# File lib/unicorn/socket_helper.rb, line 164
164: def server_cast(sock)
165: begin
166: Socket.unpack_sockaddr_in(sock.getsockname)
167: TCPServer.for_fd(sock.fileno)
168: rescue ArgumentError
169: UNIXServer.for_fd(sock.fileno)
170: end
171: end
# File lib/unicorn/socket_helper.rb, line 81
81: def set_server_sockopt(sock, opt)
82: opt ||= {}
83:
84: TCPSocket === sock and set_tcp_sockopt(sock, opt)
85:
86: if opt[:rcvbuf] || opt[:sndbuf]
87: log_buffer_sizes(sock, "before: ")
88: sock.setsockopt(SOL_SOCKET, SO_RCVBUF, opt[:rcvbuf]) if opt[:rcvbuf]
89: sock.setsockopt(SOL_SOCKET, SO_SNDBUF, opt[:sndbuf]) if opt[:sndbuf]
90: log_buffer_sizes(sock, " after: ")
91: end
92: sock.listen(opt[:backlog] || 1024)
93: rescue => e
94: if respond_to?(:logger)
95: logger.error "error setting socket options: #{e.inspect}"
96: logger.error e.backtrace.join("\n")
97: end
98: end
# File lib/unicorn/socket_helper.rb, line 49
49: def set_tcp_sockopt(sock, opt)
50:
51: # highly portable, but off by default because we don't do keepalive
52: if defined?(TCP_NODELAY) && ! (val = opt[:tcp_nodelay]).nil?
53: sock.setsockopt(IPPROTO_TCP, TCP_NODELAY, val ? 1 : 0)
54: end
55:
56: unless (val = opt[:tcp_nopush]).nil?
57: val = val ? 1 : 0
58: if defined?(TCP_CORK) # Linux
59: sock.setsockopt(IPPROTO_TCP, TCP_CORK, val)
60: elsif defined?(TCP_NOPUSH) # TCP_NOPUSH is untested (FreeBSD)
61: sock.setsockopt(IPPROTO_TCP, TCP_NOPUSH, val)
62: end
63: end
64:
65: # No good reason to ever have deferred accepts off
66: # (except maybe benchmarking)
67: if defined?(TCP_DEFER_ACCEPT)
68: # this differs from nginx, since nginx doesn't allow us to
69: # configure the the timeout...
70: tmp = { :tcp_defer_accept => true }.update(opt)
71: seconds = tmp[:tcp_defer_accept]
72: seconds = TCP_DEFER_ACCEPT_DEFAULT if seconds == true
73: seconds and sock.setsockopt(SOL_TCP, TCP_DEFER_ACCEPT, seconds)
74: elsif defined?(SO_ACCEPTFILTER) && respond_to?(:accf_arg)
75: tmp = { :accept_filter => 'httpready' }.update(opt)
76: name = tmp[:accept_filter] and
77: sock.setsockopt(SOL_SOCKET, SO_ACCEPTFILTER, accf_arg(name))
78: end
79: end
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.
# File lib/unicorn/socket_helper.rb, line 143
143: def sock_name(sock)
144: case sock
145: when String then sock
146: when UNIXServer
147: Socket.unpack_sockaddr_un(sock.getsockname)
148: when TCPServer
149: Socket.unpack_sockaddr_in(sock.getsockname).reverse!.join(':')
150: when Socket
151: begin
152: Socket.unpack_sockaddr_in(sock.getsockname).reverse!.join(':')
153: rescue ArgumentError
154: Socket.unpack_sockaddr_un(sock.getsockname)
155: end
156: else
157: raise ArgumentError, "Unhandled class #{sock.class}: #{sock.inspect}"
158: end
159: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.