From d620500dda16cfc3777894541a417d6153d5a1fb Mon Sep 17 00:00:00 2001 From: akr Date: Sun, 18 Jan 2009 07:47:35 +0000 Subject: * ext/socket/raddrinfo.c (addrinfo_ip_address): new method AddrInfo#ip_address. (addrinfo_ip_port): new method AddrInfo#ip_port. (Init_addrinfo): define the methods above. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21647 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 7 +++++ ext/socket/raddrinfo.c | 66 ++++++++++++++++++++++++++++++++++++++++++++ test/socket/test_addrinfo.rb | 4 +++ 3 files changed, 77 insertions(+) diff --git a/ChangeLog b/ChangeLog index a9aaf084dc..577ee4053a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Sun Jan 18 16:46:37 2009 Tanaka Akira + + * ext/socket/raddrinfo.c (addrinfo_ip_address): new method + AddrInfo#ip_address. + (addrinfo_ip_port): new method AddrInfo#ip_port. + (Init_addrinfo): define the methods above. + Sun Jan 18 14:29:52 2009 Tanaka Akira * ext/socket/unixsocket.c: redandant #ifdef removed. diff --git a/ext/socket/raddrinfo.c b/ext/socket/raddrinfo.c index cca244af07..ee586fac31 100644 --- a/ext/socket/raddrinfo.c +++ b/ext/socket/raddrinfo.c @@ -1520,6 +1520,70 @@ addrinfo_ip_unpack(VALUE self) return ret; } +/* + * call-seq: + * addrinfo.ip_address => string + * + * Returns the IP address as a string. + * + * AddrInfo.tcp("127.0.0.1", 80).ip_address #=> "127.0.0.1" + * AddrInfo.tcp("::1", 80).ip_address #=> "::1" + */ +static VALUE +addrinfo_ip_address(VALUE self) +{ + rb_addrinfo_t *rai = get_addrinfo(self); + int family = ai_get_afamily(rai); + VALUE vflags; + VALUE ret; + + if (!IS_IP_FAMILY(family)) + rb_raise(rb_eSocket, "need IPv4 or IPv6 address"); + + vflags = INT2NUM(NI_NUMERICHOST|NI_NUMERICSERV); + ret = addrinfo_getnameinfo(1, &vflags, self); + return rb_ary_entry(ret, 0); +} + +/* + * call-seq: + * addrinfo.ip_port => port + * + * Returns the port number as an integer. + * + * AddrInfo.tcp("127.0.0.1", 80).ip_port #=> 80 + * AddrInfo.tcp("::1", 80).ip_port #=> 80 + */ +static VALUE +addrinfo_ip_port(VALUE self) +{ + rb_addrinfo_t *rai = get_addrinfo(self); + int family = ai_get_afamily(rai); + int port; + + if (!IS_IP_FAMILY(family)) + rb_raise(rb_eSocket, "need IPv4 or IPv6 address"); + + switch (family) { + case AF_INET: + if (rai->sockaddr_len != sizeof(struct sockaddr_in)) + rb_raise(rb_eSocket, "unexpected sockaddr size for IPv4"); + port = ntohs(((struct sockaddr_in *)&rai->addr)->sin_port); + break; + + case AF_INET6: + if (rai->sockaddr_len != sizeof(struct sockaddr_in6)) + rb_raise(rb_eSocket, "unexpected sockaddr size for IPv6"); + port = ntohs(((struct sockaddr_in6 *)&rai->addr)->sin6_port); + break; + + default: + rb_raise(rb_eSocket, "need IPv4 or IPv6 address"); + } + + return INT2NUM(port); +} + #ifdef HAVE_SYS_UN_H /* * call-seq: @@ -1768,6 +1832,8 @@ Init_addrinfo(void) rb_define_method(rb_cAddrInfo, "ip?", addrinfo_ip_p, 0); rb_define_method(rb_cAddrInfo, "ip_unpack", addrinfo_ip_unpack, 0); + rb_define_method(rb_cAddrInfo, "ip_address", addrinfo_ip_address, 0); + rb_define_method(rb_cAddrInfo, "ip_port", addrinfo_ip_port, 0); rb_define_method(rb_cAddrInfo, "ipv4?", addrinfo_ipv4_p, 0); rb_define_method(rb_cAddrInfo, "ipv6?", addrinfo_ipv6_p, 0); rb_define_method(rb_cAddrInfo, "unix?", addrinfo_unix_p, 0); diff --git a/test/socket/test_addrinfo.rb b/test/socket/test_addrinfo.rb index 4e232d02a6..326c6f8a86 100644 --- a/test/socket/test_addrinfo.rb +++ b/test/socket/test_addrinfo.rb @@ -37,6 +37,8 @@ class TestSocketAddrInfo < Test::Unit::TestCase def test_addrinfo_ip_unpack ai = AddrInfo.tcp("127.0.0.1", 80) assert_equal(["127.0.0.1", 80], ai.ip_unpack) + assert_equal("127.0.0.1", ai.ip_address) + assert_equal(80, ai.ip_port) end def test_addrinfo_new_inet @@ -299,6 +301,8 @@ class TestSocketAddrInfo < Test::Unit::TestCase def test_addrinfo_ip_unpack_inet6 ai = AddrInfo.tcp("::1", 80) assert_equal(["::1", 80], ai.ip_unpack) + assert_equal("::1", ai.ip_address) + assert_equal(80, ai.ip_port) end def test_marshal_inet6 -- cgit v1.2.3