Index: ext/socket/socket.c
===================================================================
--- ext/socket/socket.c (revision 20285)
+++ ext/socket/socket.c (working copy)
@@ -1414,75 +1414,42 @@
};
static VALUE
-make_hostent_internal(struct hostent_arg *arg)
+make_hostent(struct hostent *h)
{
- VALUE host = arg->host;
- struct addrinfo* addr = arg->addr;
- VALUE (*ipaddr)(struct sockaddr*, size_t) = arg->ipaddr;
+ VALUE ary, aliases, addresses;
+ char **a;
- struct addrinfo *ai;
- struct hostent *h;
- VALUE ary, names;
- char **pch;
- const char* hostp;
- char hbuf[NI_MAXHOST];
-
ary = rb_ary_new();
- if (addr->ai_canonname) {
- hostp = addr->ai_canonname;
+ rb_ary_push(ary, rb_str_new2(h->h_name));
+
+ if (h->h_aliases) {
+ aliases = rb_ary_new();
+ for (a = h->h_aliases; *a; ++a) {
+ rb_ary_push(aliases, rb_str_new2(*a));
+ }
}
else {
- hostp = host_str(host, hbuf, sizeof(hbuf));
+ aliases = rb_ary_new2(0);
}
- rb_ary_push(ary, rb_str_new2(hostp));
+ rb_ary_push(ary, aliases);
- if (addr->ai_canonname && (h = gethostbyname(addr->ai_canonname))) {
- names = rb_ary_new();
- if (h->h_aliases != NULL) {
- for (pch = h->h_aliases; *pch; pch++) {
- rb_ary_push(names, rb_str_new2(*pch));
- }
- }
+ rb_ary_push(ary, INT2NUM(h->h_addrtype));
+
+ if (h->h_addr_list) {
+ addresses = rb_ary_new();
+ for (a = h->h_addr_list; *a; ++a) {
+ rb_ary_push(addresses, rb_str_new(*a, h->h_length));
+ }
}
else {
- names = rb_ary_new2(0);
+ addresses = rb_ary_new2(0);
}
- rb_ary_push(ary, names);
- rb_ary_push(ary, INT2NUM(addr->ai_family));
- for (ai = addr; ai; ai = ai->ai_next) {
- rb_ary_push(ary, (*ipaddr)(ai->ai_addr, ai->ai_addrlen));
- }
+ rb_ary_push(ary, addresses);
return ary;
}
static VALUE
-make_hostent(VALUE host, struct addrinfo *addr, VALUE (*ipaddr)(struct sockaddr *, size_t))
-{
- struct hostent_arg arg;
-
- arg.host = host;
- arg.addr = addr;
- arg.ipaddr = ipaddr;
- return rb_ensure(make_hostent_internal, (VALUE)&arg,
- RUBY_METHOD_FUNC(freeaddrinfo), (VALUE)addr);
-}
-
-static VALUE
-tcp_sockaddr(struct sockaddr *addr, size_t len)
-{
- return make_ipaddr(addr);
-}
-
-static VALUE
-tcp_s_gethostbyname(VALUE obj, VALUE host)
-{
- rb_secure(3);
- return make_hostent(host, sock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME),
- tcp_sockaddr);
-}
-
-static VALUE
tcp_svr_init(int argc, VALUE *argv, VALUE sock)
{
VALUE arg1, arg2;
@@ -3136,34 +3103,78 @@
return base;
}
+/*
+ * call-seq: Socket.inet_aton(host_addr) => in_addr
+ *
+ * Converts an IP address in dotted-quad notation into a
+ * struct in_addr packed as a Ruby string.
+ *
+ * === Parameters
+ * +host_addr+ - The IP address to convert.
+ *
+ * === Examples
+ * require 'socket'
+ * p Socket.gethostbyaddr(Socket.inet_aton("127.0.0.1"))
+ */
static VALUE
-sock_sockaddr(struct sockaddr *addr, size_t len)
+sock_s_inet_aton(VALUE obj, VALUE host_addr)
{
- char *ptr;
+ const char *cp;
+ struct in_addr addr;
- switch (addr->sa_family) {
- case AF_INET:
- ptr = (char*)&((struct sockaddr_in*)addr)->sin_addr.s_addr;
- len = sizeof(((struct sockaddr_in*)addr)->sin_addr.s_addr);
- break;
-#ifdef INET6
- case AF_INET6:
- ptr = (char*)&((struct sockaddr_in6*)addr)->sin6_addr.s6_addr;
- len = sizeof(((struct sockaddr_in6*)addr)->sin6_addr.s6_addr);
- break;
-#endif
- default:
- rb_raise(rb_eSocket, "unknown socket family:%d", addr->sa_family);
- break;
+ cp = StringValueCStr(host_addr);
+ if (!inet_aton(cp, &addr)) {
+ rb_raise(rb_eSocket, "invalid host address");
}
- return rb_str_new(ptr, len);
+ return rb_str_new((char *)&addr, sizeof(addr));
}
+/*
+ * call-seq: Socket.inet_ntoa(in_addr) => host_addr
+ *
+ * Converts a struct in_addr packed as a Ruby string into an IP
+ * address in dotted-quad notation.
+ *
+ * === Parameters
+ * +in_addr+ - The packed struct in_addr to convert.
+ *
+ * === Examples
+ * require 'socket'
+ * hostent = Socket.gethostbyname('localhost')
+ * hostent[3].each { |in_addr| p Socket.inet_ntoa(in_addr) }
+ */
static VALUE
+sock_s_inet_ntoa(VALUE obj, VALUE addrstr)
+{
+ struct in_addr *addr;
+
+ addr = (struct in_addr *)StringValuePtr(addrstr);
+ if (RSTRING_LEN(addrstr) != sizeof(struct in_addr)) {
+ rb_raise(rb_eSocket, "invalid address");
+ }
+ return rb_str_new2(inet_ntoa(*addr));
+}
+
+static VALUE
sock_s_gethostbyname(VALUE obj, VALUE host)
{
+ struct hostent *h;
+ char *hostp;
+
rb_secure(3);
- return make_hostent(host, sock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME), sock_sockaddr);
+
+ hostp = StringValueCStr(host);
+ h = gethostbyname(hostp);
+ if (h == NULL) {
+#ifdef HAVE_HSTRERROR
+ extern int h_errno;
+ rb_raise(rb_eSocket, "%s", (char*)hstrerror(h_errno));
+#else
+ rb_raise(rb_eSocket, "host not found");
+#endif
+ }
+
+ return make_hostent(h);
}
static VALUE
@@ -3171,49 +3182,26 @@
{
VALUE addr, type;
struct hostent *h;
- struct sockaddr *sa;
- char **pch;
- VALUE ary, names;
int t = AF_INET;
+
rb_scan_args(argc, argv, "11", &addr, &type);
- sa = (struct sockaddr*)StringValuePtr(addr);
+ StringValue(addr);
if (!NIL_P(type)) {
t = NUM2INT(type);
}
-#ifdef INET6
- else if (RSTRING_LEN(addr) == 16) {
- t = AF_INET6;
- }
-#endif
+
h = gethostbyaddr(RSTRING_PTR(addr), RSTRING_LEN(addr), t);
if (h == NULL) {
#ifdef HAVE_HSTRERROR
- extern int h_errno;
- rb_raise(rb_eSocket, "%s", (char*)hstrerror(h_errno));
+ extern int h_errno;
+ rb_raise(rb_eSocket, "%s", (char*)hstrerror(h_errno));
#else
- rb_raise(rb_eSocket, "host not found");
+ rb_raise(rb_eSocket, "host not found");
#endif
}
- ary = rb_ary_new();
- rb_ary_push(ary, rb_str_new2(h->h_name));
- names = rb_ary_new();
- rb_ary_push(ary, names);
- if (h->h_aliases != NULL) {
- for (pch = h->h_aliases; *pch; pch++) {
- rb_ary_push(names, rb_str_new2(*pch));
- }
- }
- rb_ary_push(ary, INT2NUM(h->h_addrtype));
-#ifdef h_addr
- for (pch = h->h_addr_list; *pch; pch++) {
- rb_ary_push(ary, rb_str_new(*pch, h->h_length));
- }
-#else
- rb_ary_push(ary, rb_str_new(h->h_addr, h->h_length));
-#endif
- return ary;
+ return make_hostent(h);
}
static VALUE
@@ -3632,7 +3620,6 @@
rb_define_singleton_method(rb_cIPSocket, "getaddress", ip_s_getaddress, 1);
rb_cTCPSocket = rb_define_class("TCPSocket", rb_cIPSocket);
- rb_define_singleton_method(rb_cTCPSocket, "gethostbyname", tcp_s_gethostbyname, 1);
rb_define_method(rb_cTCPSocket, "initialize", tcp_init, -1);
#ifdef SOCKS
@@ -3694,6 +3681,8 @@
rb_define_singleton_method(rb_cSocket, "socketpair", sock_s_socketpair, 3);
rb_define_singleton_method(rb_cSocket, "pair", sock_s_socketpair, 3);
rb_define_singleton_method(rb_cSocket, "gethostname", sock_gethostname, 0);
+ rb_define_singleton_method(rb_cSocket, "inet_aton", sock_s_inet_aton, 1);
+ rb_define_singleton_method(rb_cSocket, "inet_ntoa", sock_s_inet_ntoa, 1);
rb_define_singleton_method(rb_cSocket, "gethostbyname", sock_s_gethostbyname, 1);
rb_define_singleton_method(rb_cSocket, "gethostbyaddr", sock_s_gethostbyaddr, -1);
rb_define_singleton_method(rb_cSocket, "getservbyname", sock_s_getservbyname, -1);