* ext/socket/lib/socket.rb (BasicSocket#connect_address): new method.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22649 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
akr 2009-02-26 14:15:39 +00:00
Родитель cbc7f1b89b
Коммит ecb22ce2c5
4 изменённых файлов: 47 добавлений и 15 удалений

Просмотреть файл

@ -1,3 +1,7 @@
Thu Feb 26 23:14:46 2009 Tanaka Akira <akr@fsij.org>
* ext/socket/lib/socket.rb (BasicSocket#connect_address): new method.
Thu Feb 26 19:29:10 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
* hash.c (hash_foreach_iter): fix for prototype.

1
NEWS
Просмотреть файл

@ -112,6 +112,7 @@ with all sufficient information, see the ChangeLog file.
* Socket#ipv6only!
* BasicSocket#local_address
* BasicSocket#remote_address
* BasicSocket#connect_address
* BasicSocket#sendmsg
* BasicSocket#sendmsg_nonblock
* BasicSocket#recvmsg

Просмотреть файл

@ -158,6 +158,46 @@ class Addrinfo
end
end
class BasicSocket
# Returns an address of the socket suitable for connect.
#
# This method returns _self_.local_address, except following condition.
#
# - IPv4 unspecified address (0.0.0.0) is replaced by IPv4 loopback address (127.0.0.1).
# - IPv6 unspecified address (::) is replaced by IPv6 loopback address (::1).
#
# If the local address is not suitable for connect, SocketError is raised.
# IPv4 and IPv6 address which port is 0 is not suitable for connect.
# Unix domain socket which has no path is not suitable for connect.
#
# Addrinfo.tcp("0.0.0.0", 0).listen {|serv|
# p serv.connect_address #=> #<Addrinfo: 127.0.0.1:53660 TCP>
# serv.connect_address.connect {|c|
# s, _ = serv.accept
# p [c, s] #=> [#<Socket:fd 4>, #<Socket:fd 6>]
# }
# }
#
def connect_address
addr = local_address
afamily = addr.afamily
if afamily == Socket::AF_INET
raise SocketError, "unbound IPv4 socket" if addr.ip_port == 0
if addr.ip_address == "0.0.0.0"
addr = Addrinfo.new(["AF_INET", addr.ip_port, nil, "127.0.0.1"], addr.pfamily, addr.socktype, addr.protocol)
end
elsif defined?(Socket::AF_INET6) && afamily == Socket::AF_INET6
raise SocketError, "unbound IPv6 socket" if addr.ip_port == 0
if addr.ip_address == "::"
addr = Addrinfo.new(["AF_INET6", addr.ip_port, nil, "::1"], addr.pfamily, addr.socktype, addr.protocol)
end
elsif defined?(Socket::AF_UNIX) && afamily == Socket::AF_UNIX
raise SocketError, "unbound Unix socket" if addr.unix_path == ""
end
addr
end
end
class Socket
# enable the socket option IPV6_V6ONLY if IPV6_V6ONLY is available.
def ipv6only!

Просмотреть файл

@ -73,22 +73,9 @@ class TestSocket < Test::Unit::TestCase
}
end
def tcp_unspecified_to_loopback(addrinfo)
if addrinfo.ipv4? && addrinfo.ip_address == "0.0.0.0"
Addrinfo.tcp("127.0.0.1", addrinfo.ip_port)
elsif addrinfo.ipv6? && addrinfo.ipv6_unspecified?
Addrinfo.tcp("::1", addrinfo.ip_port)
elsif addrinfo.ipv6? && (ai = addrinfo.ipv6_to_ipv4) && ai.ip_address == "0.0.0.0"
Addrinfo.tcp("127.0.0.1", addrinfo.ip_port)
else
addrinfo
end
end
def test_tcp
TCPServer.open(0) {|serv|
addr = serv.local_address
addr = tcp_unspecified_to_loopback(addr)
addr = serv.connect_address
addr.connect {|s1|
s2 = serv.accept
begin
@ -185,7 +172,7 @@ class TestSocket < Test::Unit::TestCase
tcp_servers = Socket.tcp_server_sockets(0)
unix_server = Socket.unix_server_socket("#{tmpdir}/sock")
tcp_servers.each {|s|
addr = tcp_unspecified_to_loopback(s.local_address)
addr = s.connect_address
clients << addr.connect
}
clients << unix_server.local_address.connect