5 # non-portable Socket code goes here:
8 # configure platform-specific options (only tested on Linux 2.6 so far)
11 # from /usr/include/linux/tcp.h
12 TCP_DEFER_ACCEPT = 9 unless defined?(TCP_DEFER_ACCEPT)
13 TCP_CORK = 3 unless defined?(TCP_CORK)
14 when /freebsd(([1-4]\..{1,2})|5\.[0-4])/
16 # Use the HTTP accept filter if available.
17 # The struct made by pack() is defined in /usr/include/sys/socket.h
18 # as accept_filter_arg
19 unless `/sbin/sysctl -nq net.inet.accf.http`.empty?
20 unless defined?(SO_ACCEPTFILTER_HTTPREADY)
21 SO_ACCEPTFILTER_HTTPREADY = ['httpready',nil].pack('a16a240').freeze
30 UNICORN_PEERADDR = '127.0.0.1'.freeze
44 include Socket::Constants
46 def set_client_sockopt(sock)
47 sock.setsockopt(IPPROTO_TCP, TCP_NODELAY, 1) if defined?(TCP_NODELAY)
48 sock.setsockopt(SOL_TCP, TCP_CORK, 1) if defined?(TCP_CORK)
51 def set_server_sockopt(sock)
52 if defined?(TCP_DEFER_ACCEPT)
53 sock.setsockopt(SOL_TCP, TCP_DEFER_ACCEPT, 1) rescue nil
55 if defined?(SO_ACCEPTFILTER_HTTPREADY)
56 sock.setsockopt(SOL_SOCKET, SO_ACCEPTFILTER,
57 SO_ACCEPTFILTER_HTTPREADY) rescue nil
61 # creates a new server, socket. address may be a HOST:PORT or
62 # an absolute path to a UNIX socket. address can even be a Socket
63 # object in which case it is immediately returned
64 def bind_listen(address = '0.0.0.0:8080', backlog = 1024)
65 return address if address.kind_of?(Socket)
67 domain, bind_addr = if address[0..0] == "/"
68 [ AF_UNIX, Socket.pack_sockaddr_un(address) ]
69 elsif address =~ /^(\d+\.\d+\.\d+\.\d+):(\d+)$/
70 [ AF_INET, Socket.pack_sockaddr_in($2.to_i, $1) ]
72 raise ArgumentError, "Don't know how to bind: #{address}"
75 sock = Socket.new(domain, SOCK_STREAM, 0)
76 sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) if defined?(SO_REUSEADDR)
79 rescue Errno::EADDRINUSE
84 set_server_sockopt(sock) if domain == AF_INET
88 # Returns the configuration name of a socket as a string. sock may
89 # be a string value, in which case it is returned as-is
90 # Warning: TCP sockets may not always return the name given to it.
95 Socket.unpack_sockaddr_un(sock.getsockname)
97 Socket.unpack_sockaddr_in(sock.getsockname).reverse!.join(':')
100 Socket.unpack_sockaddr_in(sock.getsockname).reverse!.join(':')
102 Socket.unpack_sockaddr_un(sock.getsockname)
105 raise ArgumentError, "Unhandled class #{sock.class}: #{sock.inspect}"
109 # casts a given Socket to be a TCPServer or UNIXServer
110 def server_cast(sock)
112 Socket.unpack_sockaddr_in(sock.getsockname)
113 TCPServer.for_fd(sock.fileno)
115 UNIXServer.for_fd(sock.fileno)
119 end # module SocketHelper