Bug #743 ยป bug743.patch
| 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);
|
||