summaryrefslogtreecommitdiff
path: root/ext/socket/lib
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-02-26 14:15:39 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-02-26 14:15:39 +0000
commitecb22ce2c54a635036031c2de70473d9daf4bfd5 (patch)
treece44ae2d1b16ff12f219ade35e548432919ce328 /ext/socket/lib
parentcbc7f1b89bee06ccad0915821762c41251a97aff (diff)
* 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
Diffstat (limited to 'ext/socket/lib')
-rw-r--r--ext/socket/lib/socket.rb40
1 files changed, 40 insertions, 0 deletions
diff --git a/ext/socket/lib/socket.rb b/ext/socket/lib/socket.rb
index f83e9d6..8a5e180 100644
--- a/ext/socket/lib/socket.rb
+++ b/ext/socket/lib/socket.rb
@@ -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!