Project

General

Profile

Bug #743 ยป bug743.patch

alanwj (Alan Johnson), 11/19/2008 07:02 PM

View differences:

ext/socket/socket.c (working copy)
};
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;
......
return base;
}
/*
* call-seq: Socket.inet_aton(host_addr) => in_addr
*
* Converts an IP address in dotted-quad notation into a
* <code>struct in_addr</code> 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 <code>struct in_addr</code> packed as a Ruby string into an IP
* address in dotted-quad notation.
*
* === Parameters
* +in_addr+ - The packed <code>struct in_addr</code> 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
......
{
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
......
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
......
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);
    (1-1/1)