e$BDs0F$J$N$G$9$,!"e(Bext/socket e$B$Ge(B AddrInfo
e$B%/%i%9$r?7@_$9$k$N$O$I$&$G$7$g$&$+!#e(B
AddrInfo e$B$O4pK\E*$K$Oe(B getaddrinfo(3) e$B$Ne(B struct addrinfo
e$B$HBPe(B
e$B1~$9$k>pJs$r$b$D$b$N$H$7$^$9!#e(B
e$B$J$s$G$3$l$,M_$7$$$N$+$H$$$&M}M3$O$$$m$$$m$H$“$j$^$9$,!”$9$0e(B
e$B$K;W$$Ib$+$VM}M3$@$1$G$b0J2<$N$h$&$J$b$N$,$"$j$^$9!#e(B
- Socket.getaddrinfo e$B$NJV$jCM$,$o$+$j$K$/$$e(B
- Socket#{accept,recvfrom} e$B$,JV$9Aw?.85$,$o$+$j$K$/$$e(B
- BasicSocket#{getsockname,getpeername} e$B$,JV$9$b$N$,$o$+$j$Ke(B
e$B$/$$e(B - Socket.sockaddr_in(port, host) e$B$O0z?t$N=gHV$,5U$G8MOG$&e(B
- Socket.getaddrinfo e$B$N7k2L$r%W%m%H%3%kHs0MB8$Ke(B connect/bind
e$B$G$-$J$$e(B
e$B$^$:e(B Socket.getaddrinfo
e$B$NJV$jCM$,$o$+$j$K$/$$$H$$$&OC$G$9$,!"e(B
e$B:G6a$Ne(B [ruby-dev:37674] e$B$G;XE&$7$?LdBj$Ne(B
% ./ruby -rpp -rsocket -ve ‘pp Socket.getaddrinfo(“www.ruby-lang.org”,
80)’
ruby 1.9.1 (2009-01-01 patchlevel-5000 trunk 21253) [i686-linux]
[[“AF_INET”, 80, “carbon.ruby-lang.org”, “221.186.184.68”, 2, 2, 17]]
e$B$H$$$&Nc$G$$$&$H!"I=<($7$F$b0UL#$,$h$/$o$+$i$J$$CM$,$$$/$D$+e(B
e$B$D$$$F$$$^$9!#$7$+$7!“e(Bstruct addrinfo
e$B$KBP1~$9$k%/%i%9$,$”$j!“e(B
e$B$=$Ne(B inspecte$B$,E,@Z$KDj5A$5$l$F$$$l$P!”$b$C$H$o$+$j$d$9$$I=<(e(B
e$B$r9T$&$3$H$,$G$-$^$9!#e(BAddrInfo.getaddrinfo e$B$rDj5A$9$k$3$H$Ke(B
e$B$7$F!"e(BAddrInfo e$B$NG[Ns$rJV$9$H$9$l$P!"0J2<$N$h$&$K!"e(BTCP
e$B$H$+e(B
UDP e$B$H$$$C$?$o$+$j$d$9$$I=<($r$9$k$3$H$,=PMh$^$9!#e(B
% ./ruby -rpp -rsocket -e ‘pp AddrInfo.getaddrinfo(“www.ruby-lang.org”,
80)’
[#<AddrInfo: 221.186.184.68:80 TCP (www.ruby-lang.org:80)>,
#<AddrInfo: 221.186.184.68:80 UDP (www.ruby-lang.org:80)>]
e$B$^$?!“e(BAddrInfo e$B$Oe(B struct sockaddr
e$B$rCf$K;}$C$F$$$k$N$G!“e(B
Socket e$B%/%i%9$r;H$&$H$-$KI,MW$H$J$k!”!V%=%1%C%H%”%I%l%99=B$e(B
e$BBN$re(B pack e$B$7$?J8;zNs!W$NBe$o$j$K;H$&$3$H$,=PMh$^$9!#e(B
Socket#{accept,recvfrom} e$B$,JV$9Aw?.85$,$o$+$j$K$/$$$H$$$&$Ne(B
e$B$O!“Aw?.85$H$7$F%=%1%C%H%”%I%l%99=B$BN$rJV$9$+$i$G$9$,!"$3$le(B
e$B$re(B AddrInfo
e$B$KJQ$($k$3$H$K$h$j$o$+$j$d$9$/$9$k$3$H$,$G$-$^$9!#e(B
e$B$J$*e(B Socket#{accept_nonblock,recvfrom_nonblock} e$B$bF1MM$G$9!#e(B
e$B$?$@$7$3$NJQ99$OHs8_49$K$J$j$^$9!#$H$O$$$(!“%=%1%C%H%”%I%l%9e(B
e$B9=B$BN$r<u$1IU$1$k$H$3$m$G$Oe(B AddrInfo e$B$r<u$1IU$1$k$h$&$K$7$Fe(B
e$B$“$k$N$G!”$=$l$[$IBg$-$JLdBj$O5/$-$J$$$3$H$r4|BT$7$^$9!#$^$?!“e(B
AddrInfo#to_sockaddr e$B$Ge(B AddrInfo e$B$+$i%=%1%C%H%”%I%l%99=B$BNe(B
e$B$r<h$j=P$;$^$9$N$G!"$3$NHs8_49@-$GLdBj$,=P$?$H$-$K$O$=$l$,;He(B
e$B$($^$9!#e(B
e$B$^$?!“e(BBasicSocket#{getsockname,getpeername}
e$B$b%=%1%C%H%”%I%l%9e(B
e$B9=B$BN$rJV$9$N$G$o$+$j$K$/$$$N$G$9$,!“e(B
BasicSocket#{local_address,remote_address} e$B$H$$$&%a%=%C%I$re(B
e$B?7@$7$F$=$C$A$Oe(B AddrInfo e$B$rJV$9$h$&$K$7$F$$^$7$?!#e(B
e$B$3$C$A$”$O?7@_$J$N$GHs8_49@-$O$"$j$^$;$s!#$^$?!"e(Bgetsockname
e$B$h$je(B local_address
e$B$H$$$&L>A0$N$[$&$,$o$+$j$d$9$$$H;W$$$^$9!#e(B
BasicSocket e$B$K$D$1$?$N$Ge(B TCPSocket e$B$K$b;H$($F!"Nc$($P!"0J2<e(B
e$B$N$h$&$KF0$-$^$9!#e(B
% ./ruby -rsocket -e ’
TCPSocket.open(“localhost”, 80) {|s| p [s.local_address,
s.remote_address] }’
[#<AddrInfo: 127.0.0.1:58231 TCP>, #<AddrInfo: 127.0.0.1:80 TCP>]
IPSocket e$B$G$Oe(B addr, peeraddr e$B$,$“$j$^$9$,!”$3$l$^$?=g=x$r3Pe(B
e$B$($i$l$J$$$H$$$&LdBj$,$"$j$^$9!#e(B
% ./ruby -rsocket -e ’
TCPSocket.open(“localhost”, 80) {|s| p s.addr }’
[“AF_INET”, 58985, “localhost”, “127.0.0.1”]
e$B$5$i$K!"e(Baddr, peeraddr
e$B$OBhe(B3e$BMWAG$r5a$a$k$N$K5U0z$-$r9T$&$N$,e(B
e$BLq2p$G$9!#e(BBasicSocket.do_not_reverse_lookup = true e$B$GM^@)$Oe(B
e$B=PMh$^$9$,!"e(BAddrInfo#inspect e$B$O$=$b$=$b5U0z$-$r9T$$$^$;$s!#e(B
e$B5U0z$-$r9T$o$J$$Be$o$j$K!“e(BAddrInfo e$B$O@8@.;~$Ke(B inspect
e$BMQ$NL>e(B
e$BA0$r5-O?$G$-$^$9!#@50z$-$G%”%I%l%9$r5a$a$?;~$K$O!"85$K$J$C$?e(B
e$BL>A0$r5-O?$7$F$*$/$N$G!“e(B
#<AddrInfo: 221.186.184.68:80 TCP (www.ruby-lang.org:80)>
e$B$H$$$&$h$&$K!”%+%C%3$NCf$KL>A0$,=P$F$-$^$9!#e(B
AddrInfo e$B$r:n$kJ}K!$O$$$/$D$+MQ0U$7$^$7$?$,!“$=$NCf$Ge(B
AddrInfo.tcp(host, port) e$B$He(B AddrInfo.udp(host, port) e$B$Oe(B
Socket.sockaddr_in(port, host) e$B$N0z?t=g$N$o$+$j$K$/$5$r2r7he(B
e$B$7$F$$$^$9!#$J$*!“e(Btcp/udp e$B$N6hJL$r$7$J$$$H$$$1$J$$$N$Oe(B
AddrInfo e$B$,%=%1%C%H%”%I%l%99=B$BN$K2C$($F!”%=%1%C%H$r@8@.$9e(B
e$B$k$?$a$N>pJse(B (SOCK_STREAM/SOCK_DGRAM e$B$H$+e(B)
e$B$b;}$C$F$$$k$+$ie(B
e$B$G$9!#e(B
e$B$=$N>pJs$r;}$C$F$$$k$N$G!“e(BAddrInfo e$B$,M?$($i$l$l$P!”%=%1%C%He(B
e$B$r@8@.$7$Fe(B connect/bind e$B$9$k$3$H$,$G$-$^$9!#e(B
ai = AddrInfo.getaddrinfo(“localhost”, 80)[0] # e$B:G=i$N$d$D$r;H$&e(B
(e$BK\Ev$ONI$/$J$$e(B)
sock = Socket.new(ai.pfamily, ai.socktype, ai.protocol)
sock.connect(ai)
e$B$3$l$KBP$7!“e(BSocket.getaddrinfo e$B$r;H$&$H!”%W%m%H%3%kHs0MB8$Je(B
e$B7A$G$O5-=R$G$-$^$;$s!#e(B
ai = Socket.getaddrinfo(“localhost”, 80)[0]
sock = Socket.new(ai[4], ai[5], ai[6])
sock.connect(Socket.sockaddr_in(ai[1], ai[3]))
e$B$3$3$G!“e(BSocket.sockaddr_in e$B$r;H$C$F$$$k$N$G!”$3$l$Oe(B
IPv4/IPv6 e$B$K0MB8$7$?=q$-J}$K$J$C$F$$$^$9!#e(B
e$B$^$!!"<B:]$Ke(B getaddrinfo e$B$,e(B IPv4/IPv6
e$B0J30$K;H$($k$+$H$$$&$He(B
e$BHyL/$J$H$3$m$G$9$,!"e(BC e$B%l%Y%k$Ne(B getaddrinfo(3)
e$B$G<B8=$G$-$F$$e(B
e$B$k%W%m%H%3%kHs0MB8@-$re(B Ruby e$B$G$O$$$/$i$+<:$C$F$$$k$N$O$?$7$+e(B
e$B$G$9!#e(B
e$B$^$?!"@h$NOC$H$7$F$O!"e(B
- IPv6 e$B$G$Oe(B sendmsg/recvmsg e$B$NJd=u%G!<%?$r3hMQ$7$F$$$k$h$&$Je(B
e$B$s$G$9$,!"e(Brecvmsg e$B$G$Oe(B recvfrom
e$B$HF1MM$KAw?.85$rJV$9$N$G$d$Ce(B
e$B$Q$je(B AddrInfo e$B$r;H$$$?$$e(B - e$B%W%m%H%3%kHs0MB8$K=q$-$?$$$H$O$$$C$F$b$d$C$Q$j%“%I%l%9$KBPe(B
e$B$9$kA:n$O$?$^$KI,MW$K$J$k$N$Ge(B AddrInfo#ipv4_private? e$B$H$+e(B e$BA
:n$r2C$($?$$e(B
e$B$H$+!”$$$m$$$m9M$($i$l$^$9!#e(B
e$B$H$$$&$o$1$G$I$&$G$7$g$&$+!#Hs8_49@-$O!">e$G=R$Y$?e(B
Socket#{accept,recvfrom,accept_nonblock,recvfrom_nonblock}
e$B$@$1$J$N$G!"0-$/$J$$$s$8$c$J$$$+$H;W$&$s$G$9$,!#e(B
Index: ext/socket/socket.c
— ext/socket/socket.c (revision 21278)
+++ ext/socket/socket.c (working copy)
@@ -88,6 +88,7 @@ VALUE rb_cUNIXSocket;
VALUE rb_cUNIXServer;
#endif
VALUE rb_cSocket;
+static VALUE rb_cAddrInfo;
static VALUE rb_eSocket;
@@ -572,6 +573,88 @@ bsock_getpeername(VALUE sock)
return rb_str_new(buf, len);
}
+static VALUE addrinfo_new(struct sockaddr *, socklen_t, int, int, int,
VALUE, VALUE);
+
+static VALUE
+fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len)
+{
- /* assumes protocol family and address family are identical */
- int family = addr->sa_family;
- int socktype;
- int ret;
- socklen_t optlen = sizeof(socktype);
- ret = getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&socktype,
&optlen); - if (ret == -1) {
- rb_sys_fail(“getsockopt(SO_TYPE)”);
- }
- return addrinfo_new(addr, len, family, socktype, 0, Qnil, Qnil);
+}
+static VALUE
+io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len)
+{
- rb_io_t *fptr;
- switch (TYPE(io)) {
-
case T_FIXNUM:
-
return fd_socket_addrinfo(FIX2INT(io), addr, len);
-
case T_BIGNUM:
-
return fd_socket_addrinfo(NUM2INT(io), addr, len);
-
case T_FILE:
-
GetOpenFile(io, fptr);
-
return fd_socket_addrinfo(fptr->fd, addr, len);
-
default:
- rb_raise(rb_eTypeError, “neither IO nor file descriptor”);
- }
+}
+/*
-
- call-seq:
-
- bsock.local_address => addrinfo
-
-
- returns an AddrInfo object for local address obtained by
getsockname.
- returns an AddrInfo object for local address obtained by
-
-
- Note that addrinfo.protocol is filled by 0.
- */
+static VALUE
+bsock_local_address(VALUE sock)
+{ - char buf[1024];
- socklen_t len = sizeof buf;
- rb_io_t *fptr;
- GetOpenFile(sock, fptr);
- if (getsockname(fptr->fd, (struct sockaddr*)buf, &len) < 0)
- rb_sys_fail(“getsockname(2)”);
- return fd_socket_addrinfo(fptr->fd, (struct sockaddr *)buf, len);
+}
+/*
-
- call-seq:
-
- bsock.remote_address => addrinfo
-
-
- returns an AddrInfo object for remote address obtained by
getpeername.
- returns an AddrInfo object for remote address obtained by
-
-
- Note that addrinfo.protocol is filled by 0.
- */
+static VALUE
+bsock_remote_address(VALUE sock)
+{ - char buf[1024];
- socklen_t len = sizeof buf;
- rb_io_t *fptr;
- GetOpenFile(sock, fptr);
- if (getpeername(fptr->fd, (struct sockaddr*)buf, &len) < 0)
- rb_sys_fail(“getpeername(2)”);
- return fd_socket_addrinfo(fptr->fd, (struct sockaddr *)buf, len);
+}
struct send_arg {
int fd, flags;
VALUE mesg;
@@ -744,7 +827,7 @@ s_recvfrom(VALUE sock, int argc, VALUE *
return rb_assoc_new(str, unixaddr((struct sockaddr_un*)arg.buf,
arg.alen));
#endif
case RECV_SOCKET:
- return rb_assoc_new(str, rb_str_new(arg.buf, arg.alen));
-
return rb_assoc_new(str, io_socket_addrinfo(sock, (struct
sockaddr*)arg.buf, arg.alen));
default:
rb_bug(“s_recvfrom called with bad value”);
}
@@ -804,7 +887,7 @@ s_recvfrom_nonblock(VALUE sock, int argc
break;case RECV_SOCKET:
-
addr = rb_str_new(buf, alen);
-
addr = io_socket_addrinfo(sock, (struct sockaddr*)buf, alen); break; default:
@@ -2971,7 +3054,7 @@ sock_accept(VALUE sock)
GetOpenFile(sock, fptr);
sock2 = s_accept(rb_cSocket,fptr->fd,(struct sockaddr*)buf,&len);
- return rb_assoc_new(sock2, rb_str_new(buf, len));
- return rb_assoc_new(sock2, io_socket_addrinfo(sock2, (struct
sockaddr*)buf, len));
}
/*
@@ -3032,7 +3115,7 @@ sock_accept_nonblock(VALUE sock)
GetOpenFile(sock, fptr);
sock2 = s_accept_nonblock(rb_cSocket, fptr, (struct sockaddr *)buf,
&len);
- return rb_assoc_new(sock2, rb_str_new(buf, len));
- return rb_assoc_new(sock2, io_socket_addrinfo(sock2, (struct
sockaddr*)buf, len));
}
/*
@@ -3085,7 +3168,7 @@ sock_sysaccept(VALUE sock)
GetOpenFile(sock, fptr);
sock2 = s_accept(0,fptr->fd,(struct sockaddr*)buf,&len);
- return rb_assoc_new(sock2, rb_str_new(buf, len));
- return rb_assoc_new(sock2, io_socket_addrinfo(sock2, (struct
sockaddr*)buf, len));
}
#ifdef HAVE_GETHOSTNAME
@@ -3516,6 +3599,864 @@ sock_s_unpack_sockaddr_un(VALUE self, VA
}
#endif
+typedef struct {
- VALUE inspectname;
- VALUE canonname;
- int pfamily;
- int socktype;
- int protocol;
- struct sockaddr_storage addr;
+} rb_addrinfo_t;
+static void
+addrinfo_mark(rb_addrinfo_t *rai)
+{
- if (rai) {
-
rb_gc_mark(rai->inspectname);
-
rb_gc_mark(rai->canonname);
- }
+}
+static void
+addrinfo_free(rb_addrinfo_t *rai)
+{
- xfree(rai);
+}
+static socklen_t
+sockaddr_size(int family)
+{
- switch (family) {
-
case AF_INET: return sizeof(struct sockaddr_in);
+#ifdef INET6
-
case AF_INET6: return sizeof(struct sockaddr_in6);
+#endif
+#ifdef HAVE_SYS_UN_H
-
case AF_UNIX: return sizeof(struct sockaddr_un);
+#endif
-
default: return sizeof(struct sockaddr);
- }
+}
+static VALUE
+addrinfo_s_allocate(VALUE klass)
+{
- return Data_Wrap_Struct(klass, addrinfo_mark, addrinfo_free, 0);
+}
+#define IS_ADDRINFO(obj) (RDATA(obj)->dmark ==
(RUBY_DATA_FUNC)addrinfo_mark)
+static rb_addrinfo_t *
+check_addrinfo(VALUE self)
+{
- Check_Type(self, T_DATA);
- if (!IS_ADDRINFO(self)) {
-
rb_raise(rb_eTypeError, "wrong argument type %s (expected
AddrInfo)",
-
rb_class2name(CLASS_OF(self)));
- }
- return DATA_PTR(self);
+}
+static rb_addrinfo_t *
+get_addrinfo(VALUE self)
+{
- rb_addrinfo_t *rai = check_addrinfo(self);
- if (!rai) {
-
rb_raise(rb_eTypeError, "uninitialized socket address");
- }
- return rai;
+}
+static rb_addrinfo_t *
+alloc_addrinfo()
+{
- rb_addrinfo_t *rai = ALLOC(rb_addrinfo_t);
- memset(rai, 0, sizeof(rb_addrinfo_t));
- rai->inspectname = Qnil;
- rai->canonname = Qnil;
- return rai;
+}
+static void
+init_addrinfo(rb_addrinfo_t *rai, struct sockaddr *sa, size_t len,
-
int pfamily, int socktype, int protocol,
-
VALUE canonname, VALUE inspectname)
+{
- if (sizeof(rai->addr) < len)
-
rb_raise(rb_eArgError, "sockaddr string too big");
- memcpy((void *)&rai->addr, (void *)sa, len);
- rai->pfamily = pfamily;
- rai->socktype = socktype;
- rai->protocol = protocol;
- rai->canonname = canonname;
- rai->inspectname = inspectname;
+}
+static VALUE
+addrinfo_new(struct sockaddr *addr, socklen_t len,
-
int family, int socktype, int protocol,
-
VALUE canonname, VALUE inspectname)
+{
- VALUE a;
- rb_addrinfo_t *rai;
- a = addrinfo_s_allocate(rb_cAddrInfo);
- DATA_PTR(a) = rai = alloc_addrinfo();
- init_addrinfo(rai, addr, len, family, socktype, protocol,
canonname, inspectname); - return a;
+}
+static struct addrinfo *
+call_getaddrinfo(VALUE node, VALUE service,
-
VALUE family, VALUE socktype, VALUE protocol, VALUE
flags)
+{
- struct addrinfo hints, *res;
- MEMZERO(&hints, struct addrinfo, 1);
- hints.ai_family = NIL_P(family) ? PF_UNSPEC : family_arg(family);
- if (!NIL_P(socktype)) {
- hints.ai_socktype = socktype_arg(socktype);
- }
- if (!NIL_P(protocol)) {
- hints.ai_protocol = NUM2INT(protocol);
- }
- if (!NIL_P(flags)) {
- hints.ai_flags = NUM2INT(flags);
- }
- res = sock_getaddrinfo(node, service, &hints, 0);
- if (res == NULL)
- rb_raise(rb_eSocket, “host not found”);
- return res;
+}
+static void
+init_addrinfo_getaddrinfo(rb_addrinfo_t *rai, VALUE node, VALUE
service,
-
VALUE family, VALUE socktype, VALUE protocol,
VALUE flags,
-
VALUE inspectname)
+{
- struct addrinfo *res = call_getaddrinfo(node, service, family,
socktype, protocol, flags); - VALUE canonname;
- canonname = Qnil;
- if (res->ai_canonname) {
-
canonname = rb_tainted_str_new_cstr(res->ai_canonname);
-
OBJ_FREEZE(canonname);
- }
- init_addrinfo(rai, res->ai_addr, res->ai_addrlen,
-
NUM2INT(family), NUM2INT(socktype),
NUM2INT(protocol),
-
canonname, inspectname);
- freeaddrinfo(res);
+}
+static VALUE
+make_inspectname(VALUE node, VALUE service)
+{
- VALUE inspectname = Qnil;
- if (TYPE(node) == T_STRING) {
-
inspectname = rb_str_dup(node);
- }
- if (TYPE(service) == T_STRING) {
-
if (NIL_P(inspectname))
-
inspectname = rb_sprintf(":%s", StringValueCStr(service));
-
else
-
rb_str_catf(inspectname, ":%s", StringValueCStr(service));
- }
- else if (TYPE(service) == T_FIXNUM && FIX2INT(service) != 0)
- {
-
if (NIL_P(inspectname))
-
inspectname = rb_sprintf(":%d", FIX2INT(service));
-
else
-
rb_str_catf(inspectname, ":%d", FIX2INT(service));
- }
- if (!NIL_P(inspectname)) {
-
OBJ_INFECT(inspectname, node);
-
OBJ_INFECT(inspectname, service);
-
OBJ_FREEZE(inspectname);
- }
- return inspectname;
+}
+static VALUE
+addrinfo_firstonly_new(VALUE node, VALUE service, VALUE family, VALUE
socktype, VALUE protocol, VALUE flags)
+{
- VALUE ret;
- VALUE canonname;
- VALUE inspectname;
- struct addrinfo *res = call_getaddrinfo(node, service, family,
socktype, protocol, flags); - inspectname = make_inspectname(node, service);
- canonname = Qnil;
- if (res->ai_canonname) {
-
canonname = rb_tainted_str_new_cstr(res->ai_canonname);
-
OBJ_FREEZE(canonname);
- }
- ret = addrinfo_new(res->ai_addr, res->ai_addrlen,
-
res->ai_family, res->ai_socktype,
res->ai_protocol,
-
canonname, inspectname);
- freeaddrinfo(res);
- return ret;
+}
+static VALUE
+addrinfo_list_new(VALUE node, VALUE service, VALUE family, VALUE
socktype, VALUE protocol, VALUE flags)
+{
- VALUE ret;
- struct addrinfo *r;
- VALUE inspectname;
- struct addrinfo *res = call_getaddrinfo(node, service, family,
socktype, protocol, flags); - inspectname = make_inspectname(node, service);
- ret = rb_ary_new();
- for (r = res; r; r = r->ai_next) {
-
VALUE addr;
-
VALUE canonname = Qnil;
-
if (r->ai_canonname) {
-
canonname = rb_tainted_str_new_cstr(r->ai_canonname);
-
OBJ_FREEZE(canonname);
-
}
-
addr = addrinfo_new(r->ai_addr, r->ai_addrlen,
-
r->ai_family, r->ai_socktype,
r->ai_protocol,
-
canonname, inspectname);
-
rb_ary_push(ret, addr);
- }
- freeaddrinfo(res);
- return ret;
+}
+#ifdef HAVE_SYS_UN_H
+static VALUE
+init_unix_addrinfo(rb_addrinfo_t *rai, VALUE path)
+{
- struct sockaddr_un un;
- VALUE addr;
- StringValue(path);
- if (sizeof(un.sun_path) <= RSTRING_LEN(path))
-
rb_raise(rb_eArgError, "too long unix socket path (max:
%dbytes)",
-
(int)sizeof(un.sun_path)-1);
- MEMZERO(&un, struct sockaddr_un, 1);
- un.sun_family = AF_UNIX;
- memcpy((void*)&un.sun_path, RSTRING_PTR(path), RSTRING_LEN(path));
- init_addrinfo(rai, (struct sockaddr *)&un, sizeof(un), AF_UNIX,
SOCK_STREAM, 0, Qnil, Qnil); - return addr;
+}
+#endif
+/*
-
- call-seq:
-
- AddrInfo.new(sockaddr)
-
- AddrInfo.new(sockaddr, family)
-
- AddrInfo.new(sockaddr, family, socktype)
-
- AddrInfo.new(sockaddr, family, socktype, protocol)
-
-
- returns a new instance of AddrInfo.
-
- It the instnace contains sockaddr, family, socktype, protocol.
-
- sockaddr means struct sockaddr which can be used for connect(2),
etc.
- sockaddr means struct sockaddr which can be used for connect(2),
-
- family, socktype and protocol are integers which is used for
arguments of socket(2).
- family, socktype and protocol are integers which is used for
-
-
- sockaddr is specified as an array or a string.
-
- The array should be compatible to the value of IPSocket#addr or
UNIXSocket#addr.
- The array should be compatible to the value of IPSocket#addr or
-
- The string should be struct sockaddr as generated by
-
- Socket.sockaddr_in or Socket.unpack_sockaddr_un.
-
-
- sockaddr examples:
-
-
- [“AF_INET”, 46102, “localhost.localdomain”, “127.0.0.1”]
-
-
-
- [“AF_INET6”, 42304, “ip6-localhost”, “::1”]
-
-
-
- [“AF_UNIX”, “/tmp/sock”]
-
-
-
- Socket.sockaddr_in(“smtp”, “2001:DB8::1”)
-
-
-
- Socket.sockaddr_in(80, “172.18.22.42”)
-
-
-
- Socket.sockaddr_in(80, “www.ruby-lang.org”)
-
-
-
- Socket.sockaddr_un(“/tmp/sock”)
-
-
-
- In an AF_INET/AF_INET6 sockaddr array, the 4th element,
-
- numeric IP address, is used to construct socket address in the
AddrInfo instance.
- numeric IP address, is used to construct socket address in the
-
- The 3rd element, textual host name, is also recorded but only used
for AddrInfo#inspect.
- The 3rd element, textual host name, is also recorded but only used
-
-
- family is specified as an integer to specify the protocol family
such as Socket::PF_INET.
- family is specified as an integer to specify the protocol family
-
- It can be a symbol or a string which is the constant name
-
- with or without PF_ prefix such as :INET, :INET6, :UNIX, “PF_INET”,
etc.
- with or without PF_ prefix such as :INET, :INET6, :UNIX, “PF_INET”,
-
- If ommitted, PF_UNSPEC is assumed.
-
-
- socktype is specified as an integer to specify the socket type such
as Socket::SOCK_STREAM.
- socktype is specified as an integer to specify the socket type such
-
- It can be a symbol or a string which is the constant name
-
- with or without SOCK_ prefix such as :STREAM, :DGRAM, :RAW,
“SOCK_STREAM”, etc.
- with or without SOCK_ prefix such as :STREAM, :DGRAM, :RAW,
-
- If ommitted, 0 is assumed.
-
-
- protocol is specified as an integer to specify the protocol such as
Socket::IPPROTO_TCP.
- protocol is specified as an integer to specify the protocol such as
-
- It must be an integer, unlike family and socktype.
-
- If ommitted, 0 is assumed.
-
- Note that 0 is reasonable value for most protocols, except raw
socket.
- Note that 0 is reasonable value for most protocols, except raw
-
- */
+static VALUE
+addrinfo_initialize(int argc, VALUE *argv, VALUE self)
+{ - rb_addrinfo_t *rai;
- VALUE sockaddr_arg, sockaddr_ary, pfamily, socktype, protocol;
- int i_pfamily, i_socktype, i_protocol;
- struct sockaddr *sockaddr_ptr;
- size_t sockaddr_len;
- VALUE canonname = Qnil, inspectname = Qnil;
- if (check_addrinfo(self))
-
rb_raise(rb_eTypeError, "already initialized socket address");
- DATA_PTR(self) = rai = alloc_addrinfo();
- rb_scan_args(argc, argv, “13”, &sockaddr_arg, &pfamily, &socktype,
&protocol); - i_pfamily = NIL_P(pfamily) ? PF_UNSPEC : family_arg(pfamily);
- i_socktype = NIL_P(socktype) ? 0 : socktype_arg(socktype);
- i_protocol = NIL_P(protocol) ? 0 : NUM2INT(protocol);
- sockaddr_ary = rb_check_array_type(sockaddr_arg);
- if (!NIL_P(sockaddr_ary)) {
-
VALUE afamily = rb_ary_entry(sockaddr_ary, 0);
-
int af;
-
StringValue(afamily);
-
if (family_to_int(RSTRING_PTR(afamily), RSTRING_LEN(afamily),
&af) == -1)
-
rb_raise(rb_eSocket, "unknown address family: %s",
StringValueCStr(afamily));
-
switch (af) {
-
case AF_INET: /* ["AF_INET", 46102, "localhost.localdomain",
“127.0.0.1”] */
+#ifdef INET6
-
case AF_INET6: /* ["AF_INET6", 42304, "ip6-localhost", "::1"]
*/
+#endif
-
{
-
VALUE service = rb_ary_entry(sockaddr_ary, 1);
-
VALUE nodename = rb_ary_entry(sockaddr_ary, 2);
-
VALUE numericnode = rb_ary_entry(sockaddr_ary, 3);
-
service = INT2NUM(NUM2INT(service));
-
if (!NIL_P(nodename))
-
StringValue(nodename);
-
StringValue(numericnode);
-
init_addrinfo_getaddrinfo(rai, numericnode, service,
-
INT2NUM(i_pfamily ? i_pfamily : af),
INT2NUM(i_socktype), INT2NUM(i_protocol),
-
INT2NUM(AI_NUMERICHOST|AI_NUMERICSERV),
-
rb_str_equal(numericnode, nodename) ? Qnil :
make_inspectname(nodename, service));
-
break;
-
}
+#ifdef HAVE_SYS_UN_H
-
case AF_UNIX: /* ["AF_UNIX", "/tmp/sock"] */
-
{
-
VALUE path = rb_ary_entry(sockaddr_ary, 1);
-
StringValue(path);
-
init_unix_addrinfo(rai, path);
-
break;
-
}
+#endif
+
-
default:
-
rb_raise(rb_eSocket, "unexpected address family");
-
}
- }
- else {
-
StringValue(sockaddr_arg);
-
sockaddr_ptr = (struct sockaddr *)RSTRING_PTR(sockaddr_arg);
-
sockaddr_len = RSTRING_LEN(sockaddr_arg);
-
init_addrinfo(rai, sockaddr_ptr, sockaddr_len,
-
i_pfamily, i_socktype, i_protocol,
-
canonname, inspectname);
- }
- return self;
+}
+/*
-
- call-seq:
-
- addrinfo.inspect
-
-
- returns a string which shows addrinfo in human-readable form.
-
-
- AddrInfo.tcp(“localhost”, 80).inspect #=> “#<AddrInfo:
127.0.0.1:80 TCP (localhost:80)>”
- AddrInfo.tcp(“localhost”, 80).inspect #=> “#<AddrInfo:
-
- AddrInfo.unix(“/tmp/sock”).inspect #=> “#<AddrInfo: /tmp/sock
SOCK_STREAM>”
- AddrInfo.unix(“/tmp/sock”).inspect #=> “#<AddrInfo: /tmp/sock
-
- */
+static VALUE
+addrinfo_inspect(VALUE self)
+{ - rb_addrinfo_t *rai = get_addrinfo(self);
- int internet_p;
- VALUE ret;
- ret = rb_sprintf("#<%s: ", rb_obj_classname(self));
- switch (rai->addr.ss_family) {
-
case AF_INET:
-
{
-
struct sockaddr_in *addr = (struct sockaddr_in *)&rai->addr;
-
int port;
-
rb_str_catf(ret, "%d.%d.%d.%d",
-
((unsigned char*)&addr->sin_addr)[0],
-
((unsigned char*)&addr->sin_addr)[1],
-
((unsigned char*)&addr->sin_addr)[2],
-
((unsigned char*)&addr->sin_addr)[3]);
-
port = ntohs(addr->sin_port);
-
if (port)
-
rb_str_catf(ret, ":%d", port);
-
break;
-
}
+#ifdef INET6
-
case AF_INET6:
-
{
-
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&rai->addr;
-
char hbuf[1024];
-
int port;
-
int error;
-
/* use getnameinfo for scope_id.
-
* RFC 4007: IPv6 Scoped Address Architecture
-
* draft-ietf-ipv6-scope-api-00.txt: Scoped Address Extensions
to the IPv6 Basic Socket API
-
*/
-
error = getnameinfo((struct sockaddr *)&rai->addr,
sizeof(struct sockaddr_in6),
-
hbuf, sizeof(hbuf), NULL, 0,
-
NI_NUMERICHOST|NI_NUMERICSERV);
-
if (error) {
-
raise_socket_error("getnameinfo", error);
-
}
-
rb_str_catf(ret, "[%s]", hbuf);
-
port = ntohs(addr->sin6_port);
-
if (port)
-
rb_str_catf(ret, ":%d", port);
-
break;
-
}
+#endif
+
+#ifdef HAVE_SYS_UN_H
-
case AF_UNIX:
-
{
-
struct sockaddr_un *addr = (struct sockaddr_un *)&rai->addr;
-
if (addr->sun_path[0] == '/') { /* show absolute path as-is */
-
rb_str_catf(ret, "%.*s", sizeof(addr->sun_path),
addr->sun_path);
-
}
-
else {
-
char *s, *e;
-
rb_str_cat2(ret, "AF_UNIX");
-
s = addr->sun_path;
-
e = addr->sun_path + sizeof(addr->sun_path);
-
while (s < e && *(e-1) == '\0')
-
e--;
-
while (s < e)
-
rb_str_catf(ret, ":%02x", (unsigned char)*s++);
-
}
-
break;
-
}
+#endif
+
-
default:
-
{
-
ID id = intern_family(rai->addr.ss_family);
-
if (id == 0)
-
rb_str_catf(ret, "unknown address family %d",
rai->addr.ss_family);
-
else
-
rb_str_catf(ret, "%s address format unknown",
rb_id2name(id));
-
break;
-
}
- }
- if (rai->pfamily && rai->addr.ss_family != rai->pfamily) {
-
ID id = intern_protocol_family(rai->pfamily);
-
if (id)
-
rb_str_catf(ret, " %s", rb_id2name(id));
-
else
-
rb_str_catf(ret, " PF_\?\?\?(%d)", rai->pfamily);
- }
- internet_p = rai->pfamily == PF_INET;
+#ifdef INET6 - internet_p = internet_p || rai->pfamily == PF_INET6;
+#endif - if (internet_p && rai->socktype == SOCK_STREAM &&
-
(rai->protocol == 0 || rai->protocol == IPPROTO_TCP)) {
-
rb_str_cat2(ret, " TCP");
- }
- else if (internet_p && rai->socktype == SOCK_DGRAM &&
-
(rai->protocol == 0 || rai->protocol == IPPROTO_UDP)) {
-
rb_str_cat2(ret, " UDP");
- }
- else {
-
if (rai->socktype) {
-
ID id = intern_socktype(rai->socktype);
-
if (id)
-
rb_str_catf(ret, " %s", rb_id2name(id));
-
else
-
rb_str_catf(ret, " SOCK_\?\?\?(%d)", rai->socktype);
-
}
-
if (rai->protocol) {
-
if (internet_p) {
-
ID id = intern_ipproto(rai->protocol);
-
if (id)
-
rb_str_catf(ret, " %s", rb_id2name(id));
-
else
-
goto unknown_protocol;
-
}
-
else {
-
unknown_protocol:
-
rb_str_catf(ret, " UNKNOWN_PROTOCOL(%d)",
rai->protocol);
-
}
-
}
- }
- if (!NIL_P(rai->canonname)) {
-
VALUE name = rai->canonname;
-
rb_str_catf(ret, " %s", StringValueCStr(name));
- }
- if (!NIL_P(rai->inspectname)) {
-
VALUE name = rai->inspectname;
-
rb_str_catf(ret, " (%s)", StringValueCStr(name));
- }
- rb_str_buf_cat2(ret, “>”);
- return ret;
+}
+/*
-
- call-seq:
-
- addrinfo.afamily
-
-
- returns the address family as an integer.
-
-
- AddrInfo.tcp(“localhost”, 80).afamily == Socket::AF_INET #=> true
-
- */
+static VALUE
+addrinfo_afamily(VALUE self)
+{ - rb_addrinfo_t *rai = get_addrinfo(self);
- return INT2NUM(rai->addr.ss_family);
+}
+/*
-
- call-seq:
-
- addrinfo.pfamily
-
-
- returns the protocol family as an integer.
-
-
- AddrInfo.tcp(“localhost”, 80).pfamily == Socket::PF_INET #=> true
-
- */
+static VALUE
+addrinfo_pfamily(VALUE self)
+{ - rb_addrinfo_t *rai = get_addrinfo(self);
- return INT2NUM(rai->pfamily);
+}
+/*
-
- call-seq:
-
- addrinfo.socktype
-
-
- returns the socket type as an integer.
-
-
- AddrInfo.tcp(“localhost”, 80).socktype == Socket::SOCK_STREAM #=>
true
- AddrInfo.tcp(“localhost”, 80).socktype == Socket::SOCK_STREAM #=>
-
- */
+static VALUE
+addrinfo_socktype(VALUE self)
+{ - rb_addrinfo_t *rai = get_addrinfo(self);
- return INT2NUM(rai->socktype);
+}
+/*
-
- call-seq:
-
- addrinfo.protocol
-
-
- returns the socket type as an integer.
-
-
- AddrInfo.tcp(“localhost”, 80).protocol == Socket::IPPROTO_TCP #=>
true
- AddrInfo.tcp(“localhost”, 80).protocol == Socket::IPPROTO_TCP #=>
-
- */
+static VALUE
+addrinfo_protocol(VALUE self)
+{ - rb_addrinfo_t *rai = get_addrinfo(self);
- return INT2NUM(rai->protocol);
+}
+/*
-
- call-seq:
-
- addrinfo.to_sockaddr
-
-
- returns the socket address as packed struct sockaddr string.
-
-
- AddrInfo.tcp(“localhost”, 80).to_sockaddr
-
- #=>
“\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00”
- #=>
-
- */
+static VALUE
+addrinfo_to_sockaddr(VALUE self)
+{ - rb_addrinfo_t *rai = get_addrinfo(self);
- VALUE ret;
- ret = rb_str_new((char*)&rai->addr,
sockaddr_size(rai->addr.ss_family)); - OBJ_INFECT(ret, self);
- return ret;
+}
+/*
-
- call-seq:
-
- addrinfo.canonname
-
-
- returns the canonical name as an string.
-
-
- The canonical name is set by AddrInfo.getaddrinfo when AI_CANONNAME
is specified.
- The canonical name is set by AddrInfo.getaddrinfo when AI_CANONNAME
-
-
- list = AddrInfo.getaddrinfo(“www.ruby-lang.org”, 80, :INET,
:STREAM, nil, Socket::AI_CANONNAME)
- list = AddrInfo.getaddrinfo(“www.ruby-lang.org”, 80, :INET,
-
- p list[0] #=> #<AddrInfo: 221.186.184.68:80 TCP
carbon.ruby-lang.org (www.ruby-lang.org:80)>
- p list[0] #=> #<AddrInfo: 221.186.184.68:80 TCP
-
- p list[0].canonname #=> “carbon.ruby-lang.org”
-
- */
+static VALUE
+addrinfo_canonname(VALUE self)
+{ - rb_addrinfo_t *rai = get_addrinfo(self);
- return rai->canonname;
+}
+/*
-
- call-seq:
-
- addrinfo.inet?
-
-
- returns true if addrinfo is internet (IPv4/IPv6) address.
-
-
- AddrInfo.tcp(“127.0.0.1”, 80).inet? #=> true
-
- AddrInfo.tcp(“::1”, 80).inet? #=> true
-
- AddrInfo.unix(“/tmp/sock”).inet? #=> false
-
- */
+static VALUE
+addrinfo_inet_p(VALUE self)
+{ - rb_addrinfo_t *rai = get_addrinfo(self);
- return rai->addr.ss_family == AF_INET
+#ifdef AF_INET6 -
|| rai->addr.ss_family == AF_INET6
+#endif
-
? Qtrue : Qfalse;
- return Qfalse;
+}
+/*
-
- call-seq:
-
- addrinfo.ipv4?
-
-
- returns true if addrinfo is IPv4 address.
-
-
- AddrInfo.tcp(“127.0.0.1”, 80).ipv4? #=> true
-
- AddrInfo.tcp(“::1”, 80).ipv4? #=> false
-
- AddrInfo.unix(“/tmp/sock”).ipv4? #=> false
-
- */
+static VALUE
+addrinfo_ipv4_p(VALUE self)
+{ - rb_addrinfo_t *rai = get_addrinfo(self);
- return rai->addr.ss_family == AF_INET ? Qtrue : Qfalse;
+}
+/*
-
- call-seq:
-
- addrinfo.ipv6?
-
-
- returns true if addrinfo is IPv6 address.
-
-
- AddrInfo.tcp(“127.0.0.1”, 80).ipv6? #=> false
-
- AddrInfo.tcp(“::1”, 80).ipv6? #=> true
-
- AddrInfo.unix(“/tmp/sock”).ipv6? #=> false
-
- */
+static VALUE
+addrinfo_ipv6_p(VALUE self)
+{ - rb_addrinfo_t *rai = get_addrinfo(self);
+#ifdef AF_INET6 - return rai->addr.ss_family == AF_INET6 ? Qtrue : Qfalse;
+#else - return Qfalse;
+#endif
+}
+/*
-
- call-seq:
-
- addrinfo.unix?
-
-
- returns true if addrinfo is UNIX address.
-
-
- AddrInfo.tcp(“127.0.0.1”, 80).ipv6? #=> false
-
- AddrInfo.tcp(“::1”, 80).ipv6? #=> false
-
- AddrInfo.unix(“/tmp/sock”).ipv6? #=> true
-
- */
+static VALUE
+addrinfo_unix_p(VALUE self)
+{ - rb_addrinfo_t *rai = get_addrinfo(self);
+#ifdef AF_UNIX - return rai->addr.ss_family == AF_UNIX ? Qtrue : Qfalse;
+#else - return Qfalse;
+#endif
+}
+/*
-
- call-seq:
-
- addrinfo.getnameinfo => [nodename, service]
-
- addrinfo.getnameinfo(flags) => [nodename, service]
-
-
- returns nodename and service as a pair of strings.
-
- This converts struct sockaddr in addrinfo to textual representation.
-
-
- flags should be bitwise OR of Socket::NI_??? constants.
-
-
- AddrInfo.tcp(“127.0.0.1”, 80).getnameinfo #=> [“localhost”, “www”]
-
-
- AddrInfo.tcp(“127.0.0.1”, 80).getnameinfo(Socket::NI_NUMERICSERV)
-
- #=> [“localhost”, “80”]
- */
+static VALUE
+addrinfo_getnameinfo(int argc, VALUE *argv, VALUE self)
+{ - rb_addrinfo_t *rai = get_addrinfo(self);
- VALUE vflags;
- char hbuf[1024], pbuf[1024];
- int flags, error;
- rb_scan_args(argc, argv, “01”, &vflags);
- flags = NIL_P(vflags) ? 0 : NUM2INT(vflags);
- error = getnameinfo((struct sockaddr *)&rai->addr, sizeof(struct
sockaddr_storage), -
hbuf, sizeof(hbuf), pbuf, sizeof(pbuf),
-
flags);
- if (error) {
-
raise_socket_error("getnameinfo", error);
- }
- return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf));
+}
+/*
-
- call-seq:
-
- AddrInfo.getaddrinfo(nodename, service, family, socktype,
protocol, flags) => [addrinfo, …]
- AddrInfo.getaddrinfo(nodename, service, family, socktype,
-
- AddrInfo.getaddrinfo(nodename, service, family, socktype,
protocol) => [addrinfo, …]
- AddrInfo.getaddrinfo(nodename, service, family, socktype,
-
- AddrInfo.getaddrinfo(nodename, service, family, socktype)
=> [addrinfo, …]
- AddrInfo.getaddrinfo(nodename, service, family, socktype)
-
- AddrInfo.getaddrinfo(nodename, service, family)
=> [addrinfo, …]
- AddrInfo.getaddrinfo(nodename, service, family)
-
- AddrInfo.getaddrinfo(nodename, service)
=> [addrinfo, …]
- AddrInfo.getaddrinfo(nodename, service)
-
-
- returns a list of addrinfo objects as an array.
-
-
- This method converts nodename (hostname) and service (port) to
addrinfo.
- This method converts nodename (hostname) and service (port) to
-
- Since the conversion is not unique, the result is a list of addrinfo
objects.
- Since the conversion is not unique, the result is a list of addrinfo
-
-
- nodename or service can be nil if no conversion intended.
-
-
- family, socktype and protocol are hint for prefered protocol.
-
- If the result will be used for a socket with SOCK_STREAM,
-
- SOCK_STREAM should be specified as socktype.
-
- If so, AddrInfo.getaddrinfo returns addrinfo list appropriate for
SOCK_STREAM.
- If so, AddrInfo.getaddrinfo returns addrinfo list appropriate for
-
- If they are omitted or nil is given, the result is not restricted.
-
-
- Similary, PF_INET6 as family restricts for IPv6.
-
-
- flags should be bitwise OR of Socket::AI_??? constants.
-
-
- AddrInfo.getaddrinfo(“www.kame.net”, 80, nil, :STREAM)
-
- #=> [#<AddrInfo: 203.178.141.194:80 TCP (www.kame.net:80)>,
(www.kame.net:80)>]
-
- */
+static VALUE
+addrinfo_s_getaddrinfo(int argc, VALUE *argv, VALUE self)
+{ - VALUE node, service, family, socktype, protocol, flags;
- rb_scan_args(argc, argv, “24”, &node, &service, &family, &socktype,
&protocol, &flags); - return addrinfo_list_new(node, service, family, socktype, protocol,
flags);
+}
+/*
-
- call-seq:
-
- AddrInfo.tcp(host, port) => addrinfo
-
-
- returns an addrinfo object for TCP address.
-
-
- AddrInfo.tcp(“localhost”, “smtp”) #=> #<AddrInfo: 127.0.0.1:25 TCP
(localhost:smtp)>
- AddrInfo.tcp(“localhost”, “smtp”) #=> #<AddrInfo: 127.0.0.1:25 TCP
- */
+static VALUE
+addrinfo_s_tcp(VALUE self, VALUE host, VALUE port)
+{ - return addrinfo_firstonly_new(host, port,
-
INT2NUM(PF_UNSPEC), INT2NUM(SOCK_STREAM),
INT2FIX(IPPROTO_TCP), INT2FIX(0));
+}
+
+/*
-
- call-seq:
-
- AddrInfo.udp(host, port) => addrinfo
-
-
- returns an addrinfo object for UDP address.
-
-
- AddrInfo.udp(“localhost”, “daytime”) #=> #<AddrInfo: 127.0.0.1:13
UDP (localhost:daytime)>
- AddrInfo.udp(“localhost”, “daytime”) #=> #<AddrInfo: 127.0.0.1:13
- */
+static VALUE
+addrinfo_s_udp(VALUE self, VALUE host, VALUE port)
+{ - return addrinfo_firstonly_new(host, port,
-
INT2NUM(PF_UNSPEC), INT2NUM(SOCK_DGRAM),
INT2FIX(IPPROTO_UDP), INT2FIX(0));
+}
+
+#ifdef HAVE_SYS_UN_H
+
+/*
-
- call-seq:
-
- AddrInfo.udp(host, port) => addrinfo
-
-
- returns an addrinfo object for UNIX socket address.
-
-
- AddrInfo.unix(“/tmp/sock”) #=> #<AddrInfo: /tmp/sock SOCK_STREAM>
- */
+static VALUE
+addrinfo_s_unix(VALUE self, VALUE path)
+{ - VALUE addr;
- rb_addrinfo_t *rai;
- addr = addrinfo_s_allocate(rb_cAddrInfo);
- DATA_PTR(addr) = rai = alloc_addrinfo();
- init_unix_addrinfo(rai, path);
- OBJ_INFECT(addr, path);
- return addr;
+}
+#endif
+
static void
sock_define_const(const char *name, int value, VALUE mConst)
{
@@ -3578,6 +4519,8 @@ Init_socket()
rb_define_method(rb_cBasicSocket, “getsockopt”, bsock_getsockopt,
2);
rb_define_method(rb_cBasicSocket, “getsockname”, bsock_getsockname,
0);
rb_define_method(rb_cBasicSocket, “getpeername”, bsock_getpeername,
0);
-
rb_define_method(rb_cBasicSocket, “local_address”,
bsock_local_address, 0); -
rb_define_method(rb_cBasicSocket, “remote_address”,
bsock_remote_address, 0);
rb_define_method(rb_cBasicSocket, “send”, bsock_send, -1);
rb_define_method(rb_cBasicSocket, “recv”, bsock_recv, -1);
rb_define_method(rb_cBasicSocket, “recv_nonblock”,
bsock_recv_nonblock, -1);
@@ -3668,6 +4611,33 @@ Init_socket()
rb_define_singleton_method(rb_cSocket, “unpack_sockaddr_un”,
sock_s_unpack_sockaddr_un, 1);
#endif -
rb_cAddrInfo = rb_define_class(“AddrInfo”, rb_cData);
-
rb_define_alloc_func(rb_cAddrInfo, addrinfo_s_allocate);
-
rb_define_method(rb_cAddrInfo, “initialize”, addrinfo_initialize,
-1); -
rb_define_method(rb_cAddrInfo, “inspect”, addrinfo_inspect, 0);
-
rb_define_singleton_method(rb_cAddrInfo, “getaddrinfo”,
addrinfo_s_getaddrinfo, -1); -
rb_define_singleton_method(rb_cAddrInfo, “tcp”, addrinfo_s_tcp, 2);
-
rb_define_singleton_method(rb_cAddrInfo, “udp”, addrinfo_s_udp, 2);
+#ifdef HAVE_SYS_UN_H -
rb_define_singleton_method(rb_cAddrInfo, “unix”, addrinfo_s_unix,
1);
+#endif -
rb_define_method(rb_cAddrInfo, “afamily”, addrinfo_afamily, 0);
-
rb_define_method(rb_cAddrInfo, “pfamily”, addrinfo_pfamily, 0);
-
rb_define_method(rb_cAddrInfo, “socktype”, addrinfo_socktype, 0);
-
rb_define_method(rb_cAddrInfo, “protocol”, addrinfo_protocol, 0);
-
rb_define_method(rb_cAddrInfo, “canonname”, addrinfo_canonname, 0);
-
rb_define_method(rb_cAddrInfo, “inet?”, addrinfo_inet_p, 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);
-
rb_define_method(rb_cAddrInfo, “to_sockaddr”, addrinfo_to_sockaddr,
0); -
rb_define_method(rb_cAddrInfo, “to_str”, addrinfo_to_sockaddr, 0);
/* for compatibility */ -
rb_define_method(rb_cAddrInfo, “getnameinfo”, addrinfo_getnameinfo,
-1); -
/* constants */
mConst = rb_define_module_under(rb_cSocket, “Constants”);
init_constants(mConst);
Index: ext/socket/mkconstants.rb
===================================================================
— ext/socket/mkconstants.rb (revision 21278)
+++ ext/socket/mkconstants.rb (working copy)
@@ -172,6 +172,9 @@ def def_intern(func_name, pat, prefix_op
end
def_intern(‘intern_family’, /\AAF_/)
+def_intern(‘intern_protocol_family’, /\APF_/)
+def_intern(‘intern_socktype’, /\ASOCK_/)
+def_intern(‘intern_ipproto’, /\AIPPROTO_/)
result << ERB.new(<<‘EOS’, nil, ‘%’).result(binding)
Index: test/socket/test_socket.rb
— test/socket/test_socket.rb (revision 21278)
+++ test/socket/test_socket.rb (working copy)
@@ -102,7 +102,7 @@ class TestSocket < Test::Unit::TestCase
c = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
c.connect(serv.getsockname)
fd, peeraddr = serv.sysaccept
- assert_equal(c.getsockname, peeraddr)
- assert_equal(c.getsockname, peeraddr.to_sockaddr)
ensure
serv.close if serv
c.close if c