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

ruby-changes:11039

From: akr <ko1@a...>
Date: Wed, 25 Feb 2009 23:19:37 +0900 (JST)
Subject: [ruby-changes:11039] Ruby:r22631 (trunk): * ext/socket/ancdata.c (ancillary_s_unix_rights): new method.

akr	2009-02-25 23:19:24 +0900 (Wed, 25 Feb 2009)

  New Revision: 22631

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

  Log:
    * ext/socket/ancdata.c (ancillary_s_unix_rights): new method.

  Modified files:
    trunk/ChangeLog
    trunk/ext/socket/ancdata.c
    trunk/test/socket/test_unix.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 22630)
+++ ChangeLog	(revision 22631)
@@ -1,3 +1,7 @@
+Wed Feb 25 23:18:53 2009  Tanaka Akira  <akr@f...>
+
+	* ext/socket/ancdata.c (ancillary_s_unix_rights): new method.
+
 Wed Feb 25 23:01:26 2009  Tanaka Akira  <akr@f...>
 
 	* ext/socket/unixsocket.c (unix_recv_io): prevent FD leak when 2 fd is
Index: ext/socket/ancdata.c
===================================================================
--- ext/socket/ancdata.c	(revision 22630)
+++ ext/socket/ancdata.c	(revision 22631)
@@ -178,6 +178,51 @@
 
 /*
  * call-seq:
+ *   Socket::AncillaryData.unix_rights(io1, io2, ...) => ancillarydata
+ *
+ * Creates a new Socket::AncillaryData object which contains file descriptors as data.
+ *
+ *   p Socket::AncillaryData.unix_rights(STDERR)
+ *   #=> #<Socket::AncillaryData: UNIX SOCKET RIGHTS 2>
+ */
+static VALUE
+ancillary_s_unix_rights(int argc, VALUE *argv, VALUE klass)
+{
+#ifdef SCM_RIGHTS
+    VALUE result, str, ary;
+    int i;
+
+    ary = rb_ary_new();
+
+    for (i = 0 ; i < argc; i++) {
+        VALUE obj = argv[i];
+        if (TYPE(obj) != T_FILE) {
+            rb_raise(rb_eTypeError, "IO expected");
+        }
+        rb_ary_push(ary, obj);
+    }
+
+    str = rb_str_buf_new(sizeof(int) * argc);
+
+    for (i = 0 ; i < argc; i++) {
+        VALUE obj = RARRAY_PTR(ary)[i];
+        rb_io_t *fptr;
+        int fd;
+        GetOpenFile(obj, fptr);
+        fd = fptr->fd;
+        rb_str_buf_cat(str, (char *)&fd, sizeof(int));
+    }
+
+    result = ancdata_new(AF_UNIX, SOL_SOCKET, SCM_RIGHTS, str);
+    rb_ivar_set(result, rb_intern("unix_rights"), ary);
+    return result;
+#else
+    rb_notimplement();
+#endif
+}
+
+/*
+ * call-seq:
  *   ancillarydata.unix_rights => array-of-IOs
  *
  * returns the array of IOs which is sent by SCM_RIGHTS control message in UNIX domain socket.
@@ -1670,13 +1715,20 @@
     rb_define_method(rb_cAncillaryData, "level", ancillary_level_m, 0);
     rb_define_method(rb_cAncillaryData, "type", ancillary_type_m, 0);
     rb_define_method(rb_cAncillaryData, "data", ancillary_data, 0);
+
+    rb_define_singleton_method(rb_cAncillaryData, "unix_rights", ancillary_s_unix_rights, -1);
     rb_define_method(rb_cAncillaryData, "unix_rights", ancillary_unix_rights, 0);
+
     rb_define_method(rb_cAncillaryData, "timestamp", ancillary_timestamp, 0);
+
     rb_define_method(rb_cAncillaryData, "cmsg_is?", ancillary_cmsg_is_p, 2);
+
     rb_define_singleton_method(rb_cAncillaryData, "int", ancillary_s_int, 4);
     rb_define_method(rb_cAncillaryData, "int", ancillary_int, 0);
+
     rb_define_singleton_method(rb_cAncillaryData, "ip_pktinfo", ancillary_s_ip_pktinfo, -1);
     rb_define_method(rb_cAncillaryData, "ip_pktinfo", ancillary_ip_pktinfo, 0);
+
     rb_define_singleton_method(rb_cAncillaryData, "ipv6_pktinfo", ancillary_s_ipv6_pktinfo, 2);
     rb_define_method(rb_cAncillaryData, "ipv6_pktinfo", ancillary_ipv6_pktinfo, 0);
     rb_define_method(rb_cAncillaryData, "ipv6_pktinfo_addr", ancillary_ipv6_pktinfo_addr, 0);
Index: test/socket/test_unix.rb
===================================================================
--- test/socket/test_unix.rb	(revision 22630)
+++ test/socket/test_unix.rb	(revision 22631)
@@ -66,6 +66,41 @@
     io_ary.each {|io| io.close if !io.closed? }
   end
 
+  def test_fd_passing_n2
+    io_ary = []
+    return if !defined?(Socket::SCM_RIGHTS)
+    io_ary.concat IO.pipe
+    io_ary.concat IO.pipe
+    io_ary.concat IO.pipe
+    send_io_ary = []
+    io_ary.each {|io|
+      send_io_ary << io
+      UNIXSocket.pair {|s1, s2|
+        begin
+          ancdata = Socket::AncillaryData.unix_rights(*send_io_ary)
+          ret = s1.sendmsg("\0", 0, nil, ancdata)
+        rescue NotImplementedError
+          return
+        end
+        assert_equal(1, ret)
+        ret = s2.recvmsg
+        data, srcaddr, flags, *ctls = ret
+        recv_io_ary = []
+        ctls.each {|ctl|
+          next if ctl.level != Socket::SOL_SOCKET || ctl.type != Socket::SCM_RIGHTS
+          recv_io_ary.concat ctl.unix_rights
+        }
+        assert_equal(send_io_ary.length, recv_io_ary.length)
+        send_io_ary.length.times {|i|
+          assert_not_equal(send_io_ary[i].fileno, recv_io_ary[i].fileno)
+          assert(File.identical?(send_io_ary[i], recv_io_ary[i]))
+        }
+      }
+    }
+  ensure
+    io_ary.each {|io| io.close if !io.closed? }
+  end
+
   def test_sendmsg
     return if !defined?(Socket::SCM_RIGHTS)
     IO.pipe {|r1, w|
@@ -86,7 +121,7 @@
     }
   end
 
-  def test_sendmsg_ancillarydata
+  def test_sendmsg_ancillarydata_int
     return if !defined?(Socket::SCM_RIGHTS)
     return if !defined?(Socket::AncillaryData)
     IO.pipe {|r1, w|
@@ -108,6 +143,28 @@
     }
   end
 
+  def test_sendmsg_ancillarydata_unix_rights
+    return if !defined?(Socket::SCM_RIGHTS)
+    return if !defined?(Socket::AncillaryData)
+    IO.pipe {|r1, w|
+      UNIXSocket.pair {|s1, s2|
+        begin
+          ad = Socket::AncillaryData.unix_rights(r1)
+          ret = s1.sendmsg("\0", 0, nil, ad)
+        rescue NotImplementedError
+          return
+        end
+        assert_equal(1, ret)
+        r2 = s2.recv_io
+        begin
+          assert(File.identical?(r1, r2))
+        ensure
+          r2.close
+        end
+      }
+    }
+  end
+
   def test_recvmsg
     return if !defined?(Socket::SCM_RIGHTS)
     IO.pipe {|r1, w|

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

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