mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* ext/socket/ipsocket.c (ip_addr, ip_peeraddr),
ext/socket/socket.c (sock_s_getaddrinfo): added optional reverse_lookup flag. [ruby-core:28007] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@26590 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
e5757042f9
commit
af2f1bf4f9
3 changed files with 104 additions and 38 deletions
|
@ -1,3 +1,9 @@
|
|||
Sat Feb 6 11:35:08 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* ext/socket/ipsocket.c (ip_addr, ip_peeraddr),
|
||||
ext/socket/socket.c (sock_s_getaddrinfo): added optional
|
||||
reverse_lookup flag. [ruby-core:28007]
|
||||
|
||||
Sat Feb 6 01:55:02 2010 Yusuke Endoh <mame@tsg.ne.jp>
|
||||
|
||||
* ext/stringio/stringio.c (strio_ungetc): pads with \000 when the
|
||||
|
|
|
@ -129,61 +129,108 @@ rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv,
|
|||
inetsock_cleanup, (VALUE)&arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ipsocket.addr => [address_family, port, hostname, numeric_address]
|
||||
*
|
||||
* Returns the local address as an array which contains
|
||||
* address_family, port, hostname and numeric_address.
|
||||
*
|
||||
* hostname is obtained from numeric_address using reverse lookup.
|
||||
* If ipsocket.do_not_reverse_lookup is true,
|
||||
* hostname is same as numeric_address.
|
||||
*
|
||||
* TCPSocket.open("www.ruby-lang.org", 80) {|sock|
|
||||
* p sock.addr #=> ["AF_INET", 49429, "hal", "192.168.0.128"]
|
||||
* }
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ip_addr(VALUE sock)
|
||||
static ID id_numeric, id_hostname;
|
||||
|
||||
int
|
||||
rsock_revlookup_flag(VALUE revlookup, int *norevlookup)
|
||||
{
|
||||
rb_io_t *fptr;
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t len = sizeof addr;
|
||||
#define return_norevlookup(x) {*norevlookup = x; return 1;}
|
||||
ID id;
|
||||
|
||||
GetOpenFile(sock, fptr);
|
||||
|
||||
if (getsockname(fptr->fd, (struct sockaddr*)&addr, &len) < 0)
|
||||
rb_sys_fail("getsockname(2)");
|
||||
return rsock_ipaddr((struct sockaddr*)&addr, fptr->mode & FMODE_NOREVLOOKUP);
|
||||
switch (revlookup) {
|
||||
case Qtrue: return_norevlookup(0);
|
||||
case Qfalse: return_norevlookup(1);
|
||||
case Qnil: break;
|
||||
default:
|
||||
Check_Type(revlookup, T_SYMBOL);
|
||||
id = SYM2ID(revlookup);
|
||||
if (id == id_numeric) return_norevlookup(1);
|
||||
if (id == id_hostname) return_norevlookup(0);
|
||||
rb_raise(rb_eArgError, "invalid reverse_lookup flag: :%s", rb_id2name(id));
|
||||
}
|
||||
return 0;
|
||||
#undef return_norevlookup
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ipsocket.peeraddr => [address_family, port, hostname, numeric_address]
|
||||
* ipsocket.addr([reverse_lookup]) => [address_family, port, hostname, numeric_address]
|
||||
*
|
||||
* Returns the local address as an array which contains
|
||||
* address_family, port, hostname and numeric_address.
|
||||
*
|
||||
* If +reverse_lookup+ is +true+ or +:hostname+,
|
||||
* hostname is obtained from numeric_address using reverse lookup.
|
||||
* Or if it is +false+, or +:numeric+,
|
||||
* hostname is same as numeric_address.
|
||||
* Or if it is +nil+ or ommitted, obeys to +ipsocket.do_not_reverse_lookup+.
|
||||
* See +Socket.getaddrinfo+ also.
|
||||
*
|
||||
* TCPSocket.open("www.ruby-lang.org", 80) {|sock|
|
||||
* p sock.addr #=> ["AF_INET", 49429, "hal", "192.168.0.128"]
|
||||
* p sock.addr(true) #=> ["AF_INET", 49429, "hal", "192.168.0.128"]
|
||||
* p sock.addr(false) #=> ["AF_INET", 49429, "192.168.0.128", "192.168.0.128"]
|
||||
* p sock.addr(:hostname) #=> ["AF_INET", 49429, "hal", "192.168.0.128"]
|
||||
* p sock.addr(:numeric) #=> ["AF_INET", 49429, "192.168.0.128", "192.168.0.128"]
|
||||
* }
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ip_addr(int argc, VALUE *argv, VALUE sock)
|
||||
{
|
||||
rb_io_t *fptr;
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t len = sizeof addr;
|
||||
int norevlookup;
|
||||
|
||||
GetOpenFile(sock, fptr);
|
||||
|
||||
if (argc < 1 || !rsock_revlookup_flag(argv[0], &norevlookup))
|
||||
norevlookup = fptr->mode & FMODE_NOREVLOOKUP;
|
||||
if (getsockname(fptr->fd, (struct sockaddr*)&addr, &len) < 0)
|
||||
rb_sys_fail("getsockname(2)");
|
||||
return rsock_ipaddr((struct sockaddr*)&addr, norevlookup);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ipsocket.peeraddr([reverse_lookup]) => [address_family, port, hostname, numeric_address]
|
||||
*
|
||||
* Returns the remote address as an array which contains
|
||||
* address_family, port, hostname and numeric_address.
|
||||
* It is defined for connection oriented socket such as TCPSocket.
|
||||
*
|
||||
* If +reverse_lookup+ is +true+ or +:hostname+,
|
||||
* hostname is obtained from numeric_address using reverse lookup.
|
||||
* Or if it is +false+, or +:numeric+,
|
||||
* hostname is same as numeric_address.
|
||||
* Or if it is +nil+ or ommitted, obeys to +ipsocket.do_not_reverse_lookup+.
|
||||
* See +Socket.getaddrinfo+ also.
|
||||
*
|
||||
* TCPSocket.open("www.ruby-lang.org", 80) {|sock|
|
||||
* p sock.peeraddr #=> ["AF_INET", 80, "carbon.ruby-lang.org", "221.186.184.68"]
|
||||
* p sock.peeraddr(true) #=> ["AF_INET", 80, "221.186.184.68", "221.186.184.68"]
|
||||
* p sock.peeraddr(false) #=> ["AF_INET", 80, "221.186.184.68", "221.186.184.68"]
|
||||
* p sock.peeraddr(:hostname) #=> ["AF_INET", 80, "carbon.ruby-lang.org", "221.186.184.68"]
|
||||
* p sock.peeraddr(:numeric) #=> ["AF_INET", 80, "221.186.184.68", "221.186.184.68"]
|
||||
* }
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ip_peeraddr(VALUE sock)
|
||||
ip_peeraddr(int argc, VALUE *argv, VALUE sock)
|
||||
{
|
||||
rb_io_t *fptr;
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t len = sizeof addr;
|
||||
int norevlookup;
|
||||
|
||||
GetOpenFile(sock, fptr);
|
||||
|
||||
if (argc < 1 || !rsock_revlookup_flag(argv[0], &norevlookup))
|
||||
norevlookup = fptr->mode & FMODE_NOREVLOOKUP;
|
||||
if (getpeername(fptr->fd, (struct sockaddr*)&addr, &len) < 0)
|
||||
rb_sys_fail("getpeername(2)");
|
||||
return rsock_ipaddr((struct sockaddr*)&addr, fptr->mode & FMODE_NOREVLOOKUP);
|
||||
return rsock_ipaddr((struct sockaddr*)&addr, norevlookup);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -243,10 +290,12 @@ void
|
|||
Init_ipsocket(void)
|
||||
{
|
||||
rb_cIPSocket = rb_define_class("IPSocket", rb_cBasicSocket);
|
||||
rb_define_method(rb_cIPSocket, "addr", ip_addr, 0);
|
||||
rb_define_method(rb_cIPSocket, "peeraddr", ip_peeraddr, 0);
|
||||
rb_define_method(rb_cIPSocket, "addr", ip_addr, -1);
|
||||
rb_define_method(rb_cIPSocket, "peeraddr", ip_peeraddr, -1);
|
||||
rb_define_method(rb_cIPSocket, "recvfrom", ip_recvfrom, -1);
|
||||
rb_define_singleton_method(rb_cIPSocket, "getaddress", ip_s_getaddress, 1);
|
||||
rb_undef_method(rb_cIPSocket, "getpeereid");
|
||||
|
||||
id_numeric = rb_intern_const("numeric");
|
||||
id_hostname = rb_intern_const("hostname");
|
||||
}
|
||||
|
|
|
@ -870,7 +870,7 @@ sock_gethostname(VALUE obj)
|
|||
#endif
|
||||
|
||||
static VALUE
|
||||
make_addrinfo(struct addrinfo *res0)
|
||||
make_addrinfo(struct addrinfo *res0, int norevlookup)
|
||||
{
|
||||
VALUE base, ary;
|
||||
struct addrinfo *res;
|
||||
|
@ -880,7 +880,7 @@ make_addrinfo(struct addrinfo *res0)
|
|||
}
|
||||
base = rb_ary_new();
|
||||
for (res = res0; res; res = res->ai_next) {
|
||||
ary = rsock_ipaddr(res->ai_addr, rsock_do_not_reverse_lookup);
|
||||
ary = rsock_ipaddr(res->ai_addr, norevlookup);
|
||||
if (res->ai_canonname) {
|
||||
RARRAY_PTR(ary)[2] = rb_str_new2(res->ai_canonname);
|
||||
}
|
||||
|
@ -955,7 +955,7 @@ sock_s_gethostbyaddr(int argc, VALUE *argv)
|
|||
if (!NIL_P(family)) {
|
||||
t = rsock_family_arg(family);
|
||||
}
|
||||
#ifdef INET6
|
||||
#ifdef AF_INET6
|
||||
else if (RSTRING_LEN(addr) == 16) {
|
||||
t = AF_INET6;
|
||||
}
|
||||
|
@ -1069,7 +1069,7 @@ sock_s_getservbyport(int argc, VALUE *argv)
|
|||
|
||||
/*
|
||||
* call-seq:
|
||||
* Socket.getaddrinfo(nodename, servname[, family[, socktype[, protocol[, flags]]]]) => array
|
||||
* Socket.getaddrinfo(nodename, servname[, family[, socktype[, protocol[, flags[, reverse_lookup]]]]]) => array
|
||||
*
|
||||
* Obtains address information for _nodename_:_servname_.
|
||||
*
|
||||
|
@ -1090,14 +1090,22 @@ sock_s_getservbyport(int argc, VALUE *argv)
|
|||
* # ["AF_INET", 0, "localhost", "127.0.0.1", 2, 2, 17], # PF_INET/SOCK_DGRAM/IPPROTO_UDP
|
||||
* # ["AF_INET", 0, "localhost", "127.0.0.1", 2, 3, 0]] # PF_INET/SOCK_RAW/IPPROTO_IP
|
||||
*
|
||||
* _reverse_lookup_ directs the form of the third element, and has to
|
||||
* be one of below.
|
||||
* If it is ommitted, the default value is +nil+.
|
||||
*
|
||||
* +true+, +:hostname+: hostname is obtained from numeric address using reverse lookup, which may take a time.
|
||||
* +false+, +:numeric+: hostname is same as numeric address.
|
||||
* +nil+: obey to the current +do_not_reverse_lookup+ flag.
|
||||
*/
|
||||
static VALUE
|
||||
sock_s_getaddrinfo(int argc, VALUE *argv)
|
||||
{
|
||||
VALUE host, port, family, socktype, protocol, flags, ret;
|
||||
VALUE host, port, family, socktype, protocol, flags, ret, revlookup;
|
||||
struct addrinfo hints, *res;
|
||||
int norevlookup;
|
||||
|
||||
rb_scan_args(argc, argv, "24", &host, &port, &family, &socktype, &protocol, &flags);
|
||||
rb_scan_args(argc, argv, "25", &host, &port, &family, &socktype, &protocol, &flags, &revlookup);
|
||||
|
||||
MEMZERO(&hints, struct addrinfo, 1);
|
||||
hints.ai_family = NIL_P(family) ? PF_UNSPEC : rsock_family_arg(family);
|
||||
|
@ -1111,9 +1119,12 @@ sock_s_getaddrinfo(int argc, VALUE *argv)
|
|||
if (!NIL_P(flags)) {
|
||||
hints.ai_flags = NUM2INT(flags);
|
||||
}
|
||||
if (NIL_P(revlookup) || !rsock_revlookup_flag(revlookup, &norevlookup)) {
|
||||
norevlookup = rsock_do_not_reverse_lookup;
|
||||
}
|
||||
res = rsock_getaddrinfo(host, port, &hints, 0);
|
||||
|
||||
ret = make_addrinfo(res);
|
||||
ret = make_addrinfo(res, norevlookup);
|
||||
freeaddrinfo(res);
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue