mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* ext/socket/raddrinfo.c (addrinfo_mdump): new method.
(addrinfo_mload): new method. (Init_addrinfo): define the method above. * ext/socket/constants.c (constant_arg): str_to_int's first argument constified. * ext/socket/mkconstants.rb (gen_name_to_int_decl): generated function's first argument constified. (gen_name_to_int_func_in_guard): ditto. (ipproto_to_int): generated. * ext/socket/rubysocket.h (IS_IP_FAMILY): moved from raddrinfo.c. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21643 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
75e0fde36b
commit
86aa5043d8
6 changed files with 253 additions and 10 deletions
16
ChangeLog
16
ChangeLog
|
@ -1,3 +1,19 @@
|
|||
Sun Jan 18 03:05:20 2009 Tanaka Akira <akr@fsij.org>
|
||||
|
||||
* ext/socket/raddrinfo.c (addrinfo_mdump): new method.
|
||||
(addrinfo_mload): new method.
|
||||
(Init_addrinfo): define the method above.
|
||||
|
||||
* ext/socket/constants.c (constant_arg): str_to_int's first argument
|
||||
constified.
|
||||
|
||||
* ext/socket/mkconstants.rb (gen_name_to_int_decl): generated
|
||||
function's first argument constified.
|
||||
(gen_name_to_int_func_in_guard): ditto.
|
||||
(ipproto_to_int): generated.
|
||||
|
||||
* ext/socket/rubysocket.h (IS_IP_FAMILY): moved from raddrinfo.c.
|
||||
|
||||
Sun Jan 18 01:37:50 2009 Tanaka Akira <akr@fsij.org>
|
||||
|
||||
* ext/socket/socket.c (sock_s_getnameinfo): accept AddrInfo object.
|
||||
|
|
|
@ -19,7 +19,7 @@ static void sock_define_uconst(const char *name, unsigned int value, VALUE mCons
|
|||
#undef sock_define_uconst
|
||||
|
||||
static int
|
||||
constant_arg(VALUE arg, int (*str_to_int)(char*, int, int*), const char *errmsg)
|
||||
constant_arg(VALUE arg, int (*str_to_int)(const char*, int, int*), const char *errmsg)
|
||||
{
|
||||
VALUE tmp;
|
||||
char *ptr;
|
||||
|
|
|
@ -140,16 +140,16 @@ end
|
|||
ERB.new(<<'EOS', nil, '%').def_method(Object, "gen_name_to_int_decl(funcname, pat, prefix_optional, guard=nil)")
|
||||
%if guard
|
||||
#ifdef <%=guard%>
|
||||
int <%=funcname%>(char *str, int len, int *valp);
|
||||
int <%=funcname%>(const char *str, int len, int *valp);
|
||||
#endif
|
||||
%else
|
||||
int <%=funcname%>(char *str, int len, int *valp);
|
||||
int <%=funcname%>(const char *str, int len, int *valp);
|
||||
%end
|
||||
EOS
|
||||
|
||||
ERB.new(<<'EOS', nil, '%').def_method(Object, "gen_name_to_int_func_in_guard(funcname, pat, prefix_optional, guard=nil)")
|
||||
int
|
||||
<%=funcname%>(char *str, int len, int *valp)
|
||||
<%=funcname%>(const char *str, int len, int *valp)
|
||||
{
|
||||
switch (len) {
|
||||
% each_names_with_len(pat, prefix_optional) {|pairs, len|
|
||||
|
@ -241,6 +241,7 @@ end
|
|||
|
||||
def_name_to_int("family_to_int", /\A(AF_|PF_)/, "AF_")
|
||||
def_name_to_int("socktype_to_int", /\ASOCK_/, "SOCK_")
|
||||
def_name_to_int("ipproto_to_int", /\AIPPROTO_/, "IPPROTO_")
|
||||
def_name_to_int("level_to_int", /\A(SOL_SOCKET\z|IPPROTO_)/, /\A(SOL_|IPPROTO_)/)
|
||||
def_name_to_int("so_optname_to_int", /\ASO_/, "SO_")
|
||||
def_name_to_int("ip_optname_to_int", /\AIP_/, "IP_")
|
||||
|
|
|
@ -1081,6 +1081,196 @@ addrinfo_inspect(VALUE self)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* :nodoc: */
|
||||
static VALUE
|
||||
addrinfo_mdump(VALUE self)
|
||||
{
|
||||
rb_addrinfo_t *rai = get_addrinfo(self);
|
||||
VALUE sockaddr, afamily, pfamily, socktype, protocol, canonname, inspectname;
|
||||
int afamily_int = ai_get_afamily(rai);
|
||||
ID id;
|
||||
|
||||
id = intern_protocol_family(rai->pfamily);
|
||||
if (id == 0)
|
||||
rb_raise(rb_eSocket, "unknown protocol family: %d", rai->pfamily);
|
||||
pfamily = ID2SYM(id);
|
||||
|
||||
if (rai->socktype == 0)
|
||||
socktype = INT2FIX(0);
|
||||
else {
|
||||
id = intern_socktype(rai->socktype);
|
||||
if (id == 0)
|
||||
rb_raise(rb_eSocket, "unknown socktype: %d", rai->socktype);
|
||||
socktype = ID2SYM(id);
|
||||
}
|
||||
|
||||
if (rai->protocol == 0)
|
||||
protocol = INT2FIX(0);
|
||||
else if (IS_IP_FAMILY(afamily_int)) {
|
||||
id = intern_ipproto(rai->protocol);
|
||||
if (id == 0)
|
||||
rb_raise(rb_eSocket, "unknown IP protocol: %d", rai->protocol);
|
||||
protocol = ID2SYM(id);
|
||||
}
|
||||
else {
|
||||
rb_raise(rb_eSocket, "unknown protocol: %d", rai->protocol);
|
||||
}
|
||||
|
||||
canonname = rai->canonname;
|
||||
|
||||
inspectname = rai->inspectname;
|
||||
|
||||
id = intern_family(afamily_int);
|
||||
if (id == 0)
|
||||
rb_raise(rb_eSocket, "unknown address family: %d", afamily_int);
|
||||
afamily = ID2SYM(id);
|
||||
|
||||
switch(afamily_int) {
|
||||
case AF_UNIX:
|
||||
{
|
||||
struct sockaddr_un *su = (struct sockaddr_un *)&rai->addr;
|
||||
char *s, *e;
|
||||
s = su->sun_path;
|
||||
e = (char*)s + sizeof(su->sun_path);
|
||||
while (s < e && *(e-1) == '\0')
|
||||
e--;
|
||||
sockaddr = rb_str_new(s, e-s);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
|
||||
int error;
|
||||
error = getnameinfo((struct sockaddr *)&rai->addr, rai->sockaddr_len,
|
||||
hbuf, sizeof(hbuf), pbuf, sizeof(pbuf),
|
||||
NI_NUMERICHOST|NI_NUMERICSERV);
|
||||
if (error) {
|
||||
raise_socket_error("getnameinfo", error);
|
||||
}
|
||||
sockaddr = rb_assoc_new(rb_str_new_cstr(hbuf), rb_str_new_cstr(pbuf));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rb_ary_new3(7, afamily, sockaddr, pfamily, socktype, protocol, canonname, inspectname);
|
||||
}
|
||||
|
||||
/* :nodoc: */
|
||||
static VALUE
|
||||
addrinfo_mload(VALUE self, VALUE ary)
|
||||
{
|
||||
VALUE v;
|
||||
VALUE canonname, inspectname;
|
||||
int afamily, pfamily, socktype, protocol;
|
||||
struct sockaddr_storage ss;
|
||||
size_t len;
|
||||
const char *str;
|
||||
rb_addrinfo_t *rai;
|
||||
|
||||
if (check_addrinfo(self))
|
||||
rb_raise(rb_eTypeError, "already initialized socket address");
|
||||
|
||||
ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
|
||||
|
||||
v = rb_ary_entry(ary, 0);
|
||||
if (!SYMBOL_P(v))
|
||||
rb_raise(rb_eTypeError, "symbol expected for address family");
|
||||
str = rb_id2name(SYM2ID(v));
|
||||
if (family_to_int(str, strlen(str), &afamily) == -1)
|
||||
rb_raise(rb_eTypeError, "unexpected address family");
|
||||
|
||||
v = rb_ary_entry(ary, 2);
|
||||
if (!SYMBOL_P(v))
|
||||
rb_raise(rb_eTypeError, "symbol expected for protocol family");
|
||||
str = rb_id2name(SYM2ID(v));
|
||||
if (family_to_int(str, strlen(str), &pfamily) == -1)
|
||||
rb_raise(rb_eTypeError, "unexpected protocol family");
|
||||
|
||||
v = rb_ary_entry(ary, 3);
|
||||
if (v == INT2FIX(0))
|
||||
socktype = 0;
|
||||
else {
|
||||
if (!SYMBOL_P(v))
|
||||
rb_raise(rb_eTypeError, "symbol expected for socktype");
|
||||
str = rb_id2name(SYM2ID(v));
|
||||
if (socktype_to_int(str, strlen(str), &socktype) == -1)
|
||||
rb_raise(rb_eTypeError, "unexpected socktype");
|
||||
}
|
||||
|
||||
v = rb_ary_entry(ary, 4);
|
||||
if (v == INT2FIX(0))
|
||||
protocol = 0;
|
||||
else {
|
||||
if (!SYMBOL_P(v))
|
||||
rb_raise(rb_eTypeError, "symbol expected for protocol");
|
||||
if (IS_IP_FAMILY(afamily)) {
|
||||
str = rb_id2name(SYM2ID(v));
|
||||
if (ipproto_to_int(str, strlen(str), &protocol) == -1)
|
||||
rb_raise(rb_eTypeError, "unexpected protocol");
|
||||
}
|
||||
else {
|
||||
rb_raise(rb_eTypeError, "unexpected protocol");
|
||||
}
|
||||
}
|
||||
|
||||
v = rb_ary_entry(ary, 5);
|
||||
if (NIL_P(v))
|
||||
canonname = Qnil;
|
||||
else {
|
||||
StringValue(v);
|
||||
canonname = v;
|
||||
}
|
||||
|
||||
v = rb_ary_entry(ary, 6);
|
||||
if (NIL_P(v))
|
||||
inspectname = Qnil;
|
||||
else {
|
||||
StringValue(v);
|
||||
inspectname = v;
|
||||
}
|
||||
|
||||
v = rb_ary_entry(ary, 1);
|
||||
switch(afamily) {
|
||||
case AF_UNIX:
|
||||
{
|
||||
struct sockaddr_un *su = (struct sockaddr_un *)&ss;
|
||||
memset(su, 0, sizeof(*su));
|
||||
su->sun_family = AF_UNIX;
|
||||
|
||||
StringValue(v);
|
||||
if (sizeof(su->sun_path) <= RSTRING_LEN(v))
|
||||
rb_raise(rb_eSocket, "too long AF_UNIX path");
|
||||
memcpy(su->sun_path, RSTRING_PTR(v), RSTRING_LEN(v));
|
||||
len = sizeof(*su);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
VALUE pair = rb_convert_type(v, T_ARRAY, "Array", "to_ary");
|
||||
struct addrinfo *res;
|
||||
int flags = AI_NUMERICHOST;
|
||||
#ifdef AI_NUMERICSERV
|
||||
flags |= AI_NUMERICSERV;
|
||||
#endif
|
||||
res = call_getaddrinfo(rb_ary_entry(pair, 0), rb_ary_entry(pair, 1),
|
||||
INT2NUM(pfamily), INT2NUM(socktype), INT2NUM(protocol),
|
||||
INT2NUM(flags), 1);
|
||||
|
||||
len = res->ai_addrlen;
|
||||
memcpy(&ss, res->ai_addr, res->ai_addrlen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DATA_PTR(self) = rai = alloc_addrinfo();
|
||||
init_addrinfo(rai, (struct sockaddr *)&ss, len,
|
||||
pfamily, socktype, protocol,
|
||||
canonname, inspectname);
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* addrinfo.afamily => integer
|
||||
|
@ -1187,12 +1377,6 @@ addrinfo_canonname(VALUE self)
|
|||
return rai->canonname;
|
||||
}
|
||||
|
||||
#ifdef AF_INET6
|
||||
# define IS_IP_FAMILY(af) ((af) == AF_INET || (af) == AF_INET6)
|
||||
#else
|
||||
# define IS_IP_FAMILY(af) ((af) == AF_INET)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* addrinfo.ip? => true or false
|
||||
|
@ -1603,4 +1787,7 @@ Init_addrinfo(void)
|
|||
rb_define_method(rb_cAddrInfo, "to_sockaddr", addrinfo_to_sockaddr, 0);
|
||||
|
||||
rb_define_method(rb_cAddrInfo, "getnameinfo", addrinfo_getnameinfo, -1);
|
||||
|
||||
rb_define_method(rb_cAddrInfo, "marshal_dump", addrinfo_mdump, 0);
|
||||
rb_define_method(rb_cAddrInfo, "marshal_load", addrinfo_mload, 1);
|
||||
}
|
||||
|
|
|
@ -74,6 +74,12 @@
|
|||
# define NI_MAXSERV 32
|
||||
#endif
|
||||
|
||||
#ifdef AF_INET6
|
||||
# define IS_IP_FAMILY(af) ((af) == AF_INET || (af) == AF_INET6)
|
||||
#else
|
||||
# define IS_IP_FAMILY(af) ((af) == AF_INET)
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SOCKADDR_STORAGE
|
||||
/*
|
||||
* RFC 2553: protocol-independent placeholder for socket addresses
|
||||
|
|
|
@ -274,6 +274,17 @@ class TestSocketAddrInfo < Test::Unit::TestCase
|
|||
s2.close if s2 && !s2.closed?
|
||||
end
|
||||
|
||||
def test_marshal
|
||||
ai1 = AddrInfo.tcp("127.0.0.1", 80)
|
||||
ai2 = Marshal.load(Marshal.dump(ai1))
|
||||
assert_equal(ai1.afamily, ai2.afamily)
|
||||
assert_equal(ai1.ip_unpack, ai2.ip_unpack)
|
||||
assert_equal(ai1.pfamily, ai2.pfamily)
|
||||
assert_equal(ai1.socktype, ai2.socktype)
|
||||
assert_equal(ai1.protocol, ai2.protocol)
|
||||
assert_equal(ai1.canonname, ai2.canonname)
|
||||
end
|
||||
|
||||
if Socket.const_defined?("AF_INET6")
|
||||
|
||||
def test_addrinfo_new_inet6
|
||||
|
@ -290,6 +301,17 @@ class TestSocketAddrInfo < Test::Unit::TestCase
|
|||
assert_equal(["::1", 80], ai.ip_unpack)
|
||||
end
|
||||
|
||||
def test_marshal_inet6
|
||||
ai1 = AddrInfo.tcp("::1", 80)
|
||||
ai2 = Marshal.load(Marshal.dump(ai1))
|
||||
assert_equal(ai1.afamily, ai2.afamily)
|
||||
assert_equal(ai1.ip_unpack, ai2.ip_unpack)
|
||||
assert_equal(ai1.pfamily, ai2.pfamily)
|
||||
assert_equal(ai1.socktype, ai2.socktype)
|
||||
assert_equal(ai1.protocol, ai2.protocol)
|
||||
assert_equal(ai1.canonname, ai2.canonname)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if defined?(UNIXSocket) && /cygwin/ !~ RUBY_PLATFORM
|
||||
|
@ -325,5 +347,16 @@ class TestSocketAddrInfo < Test::Unit::TestCase
|
|||
assert(unix_ai.unix?)
|
||||
end
|
||||
|
||||
def test_marshal_unix
|
||||
ai1 = AddrInfo.unix("/var/tmp/sock")
|
||||
ai2 = Marshal.load(Marshal.dump(ai1))
|
||||
assert_equal(ai1.afamily, ai2.afamily)
|
||||
assert_equal(ai1.unix_path, ai2.unix_path)
|
||||
assert_equal(ai1.pfamily, ai2.pfamily)
|
||||
assert_equal(ai1.socktype, ai2.socktype)
|
||||
assert_equal(ai1.protocol, ai2.protocol)
|
||||
assert_equal(ai1.canonname, ai2.canonname)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue