# AddrInfo

**URL:** <https://www.ruby-forum.com/t/addrinfo/246520>\
**Category:** Development\
**Created:** [January 4, 2009, 8:46am UTC](https://www.ruby-forum.com/t/addrinfo/246520 "2009-01-04T08:46:07Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tanaka\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c67d28/32.png) [@Tanaka\_A](https://www.ruby-forum.com/u/Tanaka_A)\
**Post date:** [January 4, 2009, 8:46am UTC](https://www.ruby-forum.com/t/addrinfo/246520/1 "2009-01-04T08:46:07Z")

</div>

$BDs0F$J$N$G$9$,!"(Bext/socket $B$G(B AddrInfo  
$B%/%i%9$r?7@\_$9$k$N$O$I$&$G$7$g$&$+!#(B

AddrInfo $B$O4pK\E\*$K$O(B getaddrinfo(3) $B$N(B struct addrinfo  
$B$HBP(B  
$B1~$9$k\>pJs$r$b$D$b$N$H$7$^$9!#(B

$B$J$s$G$3$l$,M\_$7$$$N$+$H$$$&M}M3$O$$$m$$$m$H$“$j$^$9$,!”$9$0(B  
$B$K;W$$Ib$+$VM}M3$@$1$G$b0J2\<$N$h$&$J$b$N$,$"$j$^$9!#(B

- Socket.getaddrinfo $B$NJV$jCM$,$o$+$j$K$/$$(B
- Socket#{accept,recvfrom} $B$,JV$9Aw?.85$,$o$+$j$K$/$$(B
- BasicSocket#{getsockname,getpeername} $B$,JV$9$b$N$,$o$+$j$K(B  
$B$/$$(B
- Socket.sockaddr\_in(port, host) $B$O0z?t$N=gHV$,5U$G8MOG$&(B
- Socket.getaddrinfo $B$N7k2L$r%W%m%H%3%kHs0MB8$K(B connect/bind  
$B$G$-$J$$(B

$B$^$:(B Socket.getaddrinfo  
$B$NJV$jCM$,$o$+$j$K$/$$$H$$$&OC$G$9$,!"(B  
$B:G6a$N(B [ruby-dev:37674] $B$G;XE&$7$?LdBj$N(B

% ./ruby -rpp -rsocket -ve ‘pp Socket.getaddrinfo(“[www.ruby-lang.org](http://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](http://carbon.ruby-lang.org)”, “221.186.184.68”, 2, 2, 17]]

$B$H$$$&Nc$G$$$&$H!"I=\<($7$F$b0UL#$,$h$/$o$+$i$J$$CM$,$$$/$D$+(B  
$B$D$$$F$$$^$9!#$7$+$7!“(Bstruct addrinfo  
$B$KBP1~$9$k%/%i%9$,$”$j!“(B  
$B$=$N(B inspect$B$,E,@Z$KDj5A$5$l$F$$$l$P!”$b$C$H$o$+$j$d$9$$I=\<((B  
$B$r9T$&$3$H$,$G$-$^$9!#(BAddrInfo.getaddrinfo $B$rDj5A$9$k$3$H$K(B  
$B$7$F!"(BAddrInfo $B$NG[Ns$rJV$9$H$9$l$P!"0J2\<$N$h$&$K!"(BTCP  
$B$H$+(B  
UDP $B$H$$$C$?$o$+$j$d$9$$I=\<($r$9$k$3$H$,=PMh$^$9!#(B

% ./ruby -rpp -rsocket -e ‘pp AddrInfo.getaddrinfo(“[www.ruby-lang.org](http://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)\>]

$B$^$?!“(BAddrInfo $B$O(B struct sockaddr  
$B$rCf$K;}$C$F$$$k$N$G!“(B  
Socket $B%/%i%9$r;H$&$H$-$KI,MW$H$J$k!”!V%=%1%C%H%”%I%l%99=B$(B  
$BBN$r(B pack $B$7$?J8;zNs!W$NBe$o$j$K;H$&$3$H$,=PMh$^$9!#(B

Socket#{accept,recvfrom} $B$,JV$9Aw?.85$,$o$+$j$K$/$$$H$$$&$N(B  
$B$O!“Aw?.85$H$7$F%=%1%C%H%”%I%l%99=B$BN$rJV$9$+$i$G$9$,!"$3$l(B  
$B$r(B AddrInfo  
$B$KJQ$($k$3$H$K$h$j$o$+$j$d$9$/$9$k$3$H$,$G$-$^$9!#(B  
$B$J$\*(B Socket#{accept\_nonblock,recvfrom\_nonblock} $B$bF1MM$G$9!#(B

$B$?$@$7$3$NJQ99$OHs8\_49$K$J$j$^$9!#$H$O$$$(!“%=%1%C%H%”%I%l%9(B  
$B9=B$BN$r\<u$1IU$1$k$H$3$m$G$O(B AddrInfo $B$r\<u$1IU$1$k$h$&$K$7$F(B  
$B$“$k$N$G!”$=$l$[$IBg$-$JLdBj$O5/$-$J$$$3$H$r4|BT$7$^$9!#$^$?!“(B  
AddrInfo#to\_sockaddr $B$G(B AddrInfo $B$+$i%=%1%C%H%”%I%l%99=B$BN(B  
$B$r\<h$j=P$;$^$9$N$G!"$3$NHs8\_49@-$GLdBj$,=P$?$H$-$K$O$=$l$,;H(B  
$B$($^$9!#(B

$B$^$?!“(BBasicSocket#{getsockname,getpeername}  
$B$b%=%1%C%H%”%I%l%9(B  
$B9=B$BN$rJV$9$N$G$o$+$j$K$/$$$N$G$9$,!“(B  
BasicSocket#{local\_address,remote\_address} $B$H$$$&%a%=%C%I$r(B  
$B?7@_$7$F$=$C$A$O(B AddrInfo $B$rJV$9$h$&$K$7$F$_$^$7$?!#(B  
$B$3$C$A$”$O?7@\_$J$N$GHs8\_49@-$O$"$j$^$;$s!#$^$?!"(Bgetsockname  
$B$h$j(B local\_address  
$B$H$$$&L\>A0$N$[$&$,$o$+$j$d$9$$$H;W$$$^$9!#(B

BasicSocket $B$K$D$1$?$N$G(B TCPSocket $B$K$b;H$($F!"Nc$($P!"0J2\<(B  
$B$N$h$&$KF0$-$^$9!#(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 $B$G$O(B addr, peeraddr $B$,$“$j$^$9$,!”$3$l$^$?=g=x$r3P(B  
$B$($i$l$J$$$H$$$&LdBj$,$"$j$^$9!#(B

% ./ruby -rsocket -e ’  
TCPSocket.open(“localhost”, 80) {|s| p s.addr }’  
[“AF\_INET”, 58985, “localhost”, “127.0.0.1”]

$B$5$i$K!"(Baddr, peeraddr  
$B$OBh(B3$BMWAG$r5a$a$k$N$K5U0z$-$r9T$&$N$,(B  
$BLq2p$G$9!#(BBasicSocket.do\_not\_reverse\_lookup = true $B$GM^@)$O(B  
$B=PMh$^$9$,!"(BAddrInfo#inspect $B$O$=$b$=$b5U0z$-$r9T$$$^$;$s!#(B  
$B5U0z$-$r9T$o$J$$Be$o$j$K!“(BAddrInfo $B$O@8@.;~$K(B inspect  
$BMQ$NL\>(B  
$BA0$r5-O?$G$-$^$9!#@50z$-$G%”%I%l%9$r5a$a$?;~$K$O!"85$K$J$C$?(B  
$BL\>A0$r5-O?$7$F$\*$/$N$G!“(B  
#\<AddrInfo: 221.186.184.68:80 TCP (www.ruby-lang.org:80)\>  
$B$H$$$&$h$&$K!”%+%C%3$NCf$KL\>A0$,=P$F$-$^$9!#(B

AddrInfo $B$r:n$kJ}K!$O$$$/$D$+MQ0U$7$^$7$?$,!“$=$NCf$G(B  
AddrInfo.tcp(host, port) $B$H(B AddrInfo.udp(host, port) $B$O(B  
Socket.sockaddr\_in(port, host) $B$N0z?t=g$N$o$+$j$K$/$5$r2r7h(B  
$B$7$F$$$^$9!#$J$\*!“(Btcp/udp $B$N6hJL$r$7$J$$$H$$$1$J$$$N$O(B  
AddrInfo $B$,%=%1%C%H%”%I%l%99=B$BN$K2C$($F!”%=%1%C%H$r@8@.$9(B  
$B$k$?$a$N\>pJs(B (SOCK\_STREAM/SOCK\_DGRAM $B$H$+(B)  
$B$b;}$C$F$$$k$+$i(B  
$B$G$9!#(B

$B$=$N\>pJs$r;}$C$F$$$k$N$G!“(BAddrInfo $B$,M?$($i$l$l$P!”%=%1%C%H(B  
$B$r@8@.$7$F(B connect/bind $B$9$k$3$H$,$G$-$^$9!#(B

ai = AddrInfo.getaddrinfo(“localhost”, 80)[0] # $B:G=i$N$d$D$r;H$&(B  
($BK\Ev$ONI$/$J$$(B)  
sock = Socket.new(ai.pfamily, ai.socktype, ai.protocol)  
sock.connect(ai)

$B$3$l$KBP$7!“(BSocket.getaddrinfo $B$r;H$&$H!”%W%m%H%3%kHs0MB8$J(B  
$B7A$G$O5-=R$G$-$^$;$s!#(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]))

$B$3$3$G!“(BSocket.sockaddr\_in $B$r;H$C$F$$$k$N$G!”$3$l$O(B  
IPv4/IPv6 $B$K0MB8$7$?=q$-J}$K$J$C$F$$$^$9!#(B

$B$^$!!"\<B:]$K(B getaddrinfo $B$,(B IPv4/IPv6  
$B0J30$K;H$($k$+$H$$$&$H(B  
$BHyL/$J$H$3$m$G$9$,!"(BC $B%l%Y%k$N(B getaddrinfo(3)  
$B$G\<B8=$G$-$F$$(B  
$B$k%W%m%H%3%kHs0MB8@-$r(B Ruby $B$G$O$$$/$i$+\<:$C$F$$$k$N$O$?$7$+(B  
$B$G$9!#(B

$B$^$?!"@h$NOC$H$7$F$O!"(B

- IPv6 $B$G$O(B sendmsg/recvmsg $B$NJd=u%G!\<%?$r3hMQ$7$F$$$k$h$&$J(B  
$B$s$G$9$,!"(Brecvmsg $B$G$O(B recvfrom  
$B$HF1MM$KAw?.85$rJV$9$N$G$d$C(B  
$B$Q$j(B AddrInfo $B$r;H$$$?$$(B
- $B%W%m%H%3%kHs0MB8$K=q$-$?$$$H$O$$$C$F$b$d$C$Q$j%“%I%l%9$KBP(B  
$B$9$kA`:n$O$?$^$KI,MW$K$J$k$N$G(B AddrInfo#ipv4_private? $B$H$+(B $BA`:n$r2C$($?$$(B  
$B$H$+!”$$$m$$$m9M$($i$l$^$9!#(B

$B$H$$$&$o$1$G$I$&$G$7$g$&$+!#Hs8\_49@-$O!"\>e$G=R$Y$?(B  
Socket#{accept,recvfrom,accept\_nonblock,recvfrom\_nonblock}  
$B$@$1$J$N$G!"0-$/$J$$$s$8$c$J$$$+$H;W$&$s$G$9$,!#(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.

- 
  - 

- 
  - 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.

- 
  - 

- 
  - 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;

- 

```
   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.

- 
  - family, socktype and protocol are integers which is used for  
arguments of socket(2).

- 
  - 

- 
  - sockaddr is specified as an array or a string.

- 
  - The array should be compatible to the value of IPSocket#addr or  
UNIXSocket#addr.

- 
  - 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](http://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.

- 
  - The 3rd element, textual host name, is also recorded but only used  
for AddrInfo#inspect.

- 
  - 

- 
  - family is specified as an integer to specify the protocol family  
such as Socket::PF\_INET.

- 
  - 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.

- 
  - If ommitted, PF\_UNSPEC is assumed.

- 
  - 

- 
  - socktype is specified as an integer to specify the socket type such  
as Socket::SOCK\_STREAM.

- 
  - 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.

- 
  - If ommitted, 0 is assumed.

- 
  - 

- 
  - protocol is specified as an integer to specify the protocol such as  
Socket::IPPROTO\_TCP.

- 
  - 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.

- 
  - 

- \*/  
+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.unix(“/tmp/sock”).inspect #=\> “#\<AddrInfo: /tmp/sock  
SOCK\_STREAM\>”

- 
  - 

- \*/  
+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

- 
  - 

- \*/  
+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

- 
  - 

- \*/  
+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.

- 
  - 

- 
  - list = AddrInfo.getaddrinfo(“[www.ruby-lang.org](http://www.ruby-lang.org)”, 80, :INET,  
:STREAM, nil, Socket::AI\_CANONNAME)

- 
  - p list[0] #=\> #\<AddrInfo: 221.186.184.68:80 TCP  
[carbon.ruby-lang.org](http://carbon.ruby-lang.org) (www.ruby-lang.org:80)\>

- 
  - p list[0].canonname #=\> “[carbon.ruby-lang.org](http://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,  
protocol) =\> [addrinfo, …]

- 
  - AddrInfo.getaddrinfo(nodename, service, family, socktype)  
=\> [addrinfo, …]

- 
  - AddrInfo.getaddrinfo(nodename, service, family)  
=\> [addrinfo, …]

- 
  - AddrInfo.getaddrinfo(nodename, service)  
=\> [addrinfo, …]

- 
  - 

- 
  - returns a list of addrinfo objects as an array.

- 
  - 

- 
  - This method converts nodename (hostname) and service (port) to  
addrinfo.

- 
  - Since the conversion is not unique, the result is a list of addrinfo  
objects.

- 
  - 

- 
  - 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 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](http://www.kame.net)”, 80, nil, :STREAM)

- 
  - #=\> [#\<AddrInfo: 203.178.141.194:80 TCP (www.kame.net:80)\>,

- 
  - 
# #\<AddrInfo: [2001:200:0:8002:203:47ff:fea5:3085]:80 TCP

(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)\>

- \*/  
+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)\>

- \*/  
+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
