[前][次][番号順一覧][スレッド一覧]

ruby-changes:10100

From: akr <ko1@a...>
Date: Sun, 18 Jan 2009 03:14:55 +0900 (JST)
Subject: [ruby-changes:10100] Ruby:r21643 (trunk): * ext/socket/raddrinfo.c (addrinfo_mdump): new method.

akr	2009-01-18 03:14:34 +0900 (Sun, 18 Jan 2009)

  New Revision: 21643

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=21643

  Log:
    * 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.

  Modified files:
    trunk/ChangeLog
    trunk/ext/socket/constants.c
    trunk/ext/socket/mkconstants.rb
    trunk/ext/socket/raddrinfo.c
    trunk/ext/socket/rubysocket.h
    trunk/test/socket/test_addrinfo.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 21642)
+++ ChangeLog	(revision 21643)
@@ -1,3 +1,19 @@
+Sun Jan 18 03:05:20 2009  Tanaka Akira  <akr@f...>
+
+	* 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@f...>
 
 	* ext/socket/socket.c (sock_s_getnameinfo): accept AddrInfo object.
Index: ext/socket/rubysocket.h
===================================================================
--- ext/socket/rubysocket.h	(revision 21642)
+++ ext/socket/rubysocket.h	(revision 21643)
@@ -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
Index: ext/socket/raddrinfo.c
===================================================================
--- ext/socket/raddrinfo.c	(revision 21642)
+++ ext/socket/raddrinfo.c	(revision 21643)
@@ -1081,6 +1081,196 @@
     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 @@
     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 @@
     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);
 }
Index: ext/socket/constants.c
===================================================================
--- ext/socket/constants.c	(revision 21642)
+++ ext/socket/constants.c	(revision 21643)
@@ -19,7 +19,7 @@
 #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;
Index: ext/socket/mkconstants.rb
===================================================================
--- ext/socket/mkconstants.rb	(revision 21642)
+++ ext/socket/mkconstants.rb	(revision 21643)
@@ -140,16 +140,16 @@
 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 @@
 
 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_")
Index: test/socket/test_addrinfo.rb
===================================================================
--- test/socket/test_addrinfo.rb	(revision 21642)
+++ test/socket/test_addrinfo.rb	(revision 21643)
@@ -274,6 +274,17 @@
     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 @@
       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 @@
       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

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]