1
0
Fork 0
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:
akr 2009-01-17 18:14:34 +00:00
parent 75e0fde36b
commit 86aa5043d8
6 changed files with 253 additions and 10 deletions

View file

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

View file

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

View file

@ -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_")

View file

@ -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);
}

View file

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

View file

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