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

ruby-changes:10856

From: akr <ko1@a...>
Date: Thu, 19 Feb 2009 03:43:32 +0900 (JST)
Subject: [ruby-changes:10856] Ruby:r22426 (trunk): * ext/socket/ancdata.c (ancillary_rights): new method.

akr	2009-02-19 03:43:15 +0900 (Thu, 19 Feb 2009)

  New Revision: 22426

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

  Log:
    * ext/socket/ancdata.c (ancillary_rights): new method.
      (make_io_for_rights): new function to allocate
      IOs for FDs in SCM_RIGHTS message.
      (bsock_recvmsg_internal): use make_io_for_rights.  So the FDs can be
      closed by GC.

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

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 22425)
+++ ChangeLog	(revision 22426)
@@ -1,3 +1,11 @@
+Thu Feb 19 03:42:48 2009  Tanaka Akira  <akr@f...>
+
+	* ext/socket/ancdata.c (ancillary_rights): new method.
+	  (make_io_for_rights): new function to allocate
+	  IOs for FDs in SCM_RIGHTS message.
+	  (bsock_recvmsg_internal): use make_io_for_rights.  So the FDs can be
+	  closed by GC.
+
 Thu Feb 19 03:28:59 2009  Akinori MUSHA  <knu@i...>
 
 	* README.EXT, README.EXT.ja: Improve the document about
Index: ext/socket/ancdata.c
===================================================================
--- ext/socket/ancdata.c	(revision 22425)
+++ ext/socket/ancdata.c	(revision 22426)
@@ -174,6 +174,29 @@
     return v;
 }
 
+/*
+ * call-seq:
+ *   ancillarydata.rights => array-of-IOs
+ *
+ * returns the array of IOs which is sent by SCM_RIGHTS control message.
+ *
+ * The class of an IO in the array is IO or Socket. 
+ *
+ *   s1, s2 = UNIXSocket.pair
+ *   p s1                                       #=> #<UNIXSocket:fd 3>
+ *   s1.sendmsg "standard IOs", 0, nil, [:SOCKET, :RIGHTS, [0,s1.fileno].pack("ii")]
+ *   _, _, _, ctl = s2.recvmsg
+ *   p ctl.rights                               #=> [#<IO:fd 6>, #<Socket:fd 7>]
+ *   p File.identical?(STDIN, ctl.rights[0])    #=> true
+ *   p File.identical?(s1, ctl.rights[1])       #=> true
+ *
+ */
+static VALUE
+ancillary_rights(VALUE self)
+{
+    VALUE v = rb_attr_get(self, rb_intern("rights"));
+    return v;
+}
 
 /*
  * call-seq:
@@ -1121,6 +1144,35 @@
 #endif
 }
 
+#if defined(HAVE_ST_MSG_CONTROL)
+static void
+make_io_for_rights(VALUE ctl, struct cmsghdr *cmh)
+{
+    if (cmh->cmsg_level == SOL_SOCKET && cmh->cmsg_type == SCM_RIGHTS) {
+        int *fdp = (int *)CMSG_DATA(cmh);
+        int *end = (int *)((char *)cmh + cmh->cmsg_len);
+        while (fdp < end) {
+            int fd = *fdp;
+            struct stat stbuf;
+            VALUE io, ary;
+            if (fstat(fd, &stbuf) == -1)
+                rb_raise(rb_eSocket, "invalid fd in SCM_RIGHTS");
+            if (S_ISSOCK(stbuf.st_mode))
+                io = init_sock(rb_obj_alloc(rb_cSocket), fd);
+            else
+                io = rb_io_fdopen(fd, O_RDWR, NULL);
+            ary = rb_attr_get(ctl, rb_intern("rights"));
+            if (NIL_P(ary)) {
+                ary = rb_ary_new();
+                rb_ivar_set(ctl, rb_intern("rights"), ary);
+            }
+            rb_ary_push(ary, io);
+            fdp++;
+        }
+    }
+}
+#endif
+
 static VALUE
 bsock_recvmsg_internal(int argc, VALUE *argv, VALUE sock, int nonblock)
 {
@@ -1145,6 +1197,7 @@
     } ctlbuf0;
     char *ctlbuf;
     VALUE ctl_str = Qnil;
+    int family;
 #endif
 
     rb_secure(4);
@@ -1288,17 +1341,17 @@
 			 );
 
 #if defined(HAVE_ST_MSG_CONTROL)
+    family = rb_sock_getfamily(fptr->fd);
     if (mh.msg_controllen) {
         for (cmh = CMSG_FIRSTHDR(&mh); cmh != NULL; cmh = CMSG_NXTHDR(&mh, cmh)) {
             VALUE ctl;
             size_t clen;
-            int family;
             if (cmh->cmsg_len == 0) {
                 rb_raise(rb_eIOError, "invalid control message (cmsg_len == 0)");
             }
-            family = rb_sock_getfamily(fptr->fd);
             clen = (char*)cmh + cmh->cmsg_len - (char*)CMSG_DATA(cmh);
             ctl = ancdata_new(family, cmh->cmsg_level, cmh->cmsg_type, rb_tainted_str_new((char*)CMSG_DATA(cmh), clen));
+            make_io_for_rights(ctl, cmh);
             rb_ary_push(ret, ctl);
         }
     }
@@ -1398,6 +1451,7 @@
     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_method(rb_cAncillaryData, "rights", ancillary_rights, 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);
Index: test/socket/test_unix.rb
===================================================================
--- test/socket/test_unix.rb	(revision 22425)
+++ test/socket/test_unix.rb	(revision 22426)
@@ -53,7 +53,7 @@
         recv_io_ary = []
         ctls.each {|ctl|
           next if ctl.level != Socket::SOL_SOCKET || ctl.type != Socket::SCM_RIGHTS
-          recv_io_ary.concat ctl.data.unpack("i!*").map {|fd| IO.new(fd) }
+          recv_io_ary.concat ctl.rights
         }
         assert_equal(send_io_ary.length, recv_io_ary.length)
         send_io_ary.length.times {|i|
@@ -126,13 +126,14 @@
 	  assert_instance_of(Addrinfo, srcaddr)
 	  assert_instance_of(Array, ctls)
 	  assert_equal(1, ctls.length)
-	  assert_instance_of(Socket::AncillaryData, ctls[0])
-	  assert_equal(Socket::SOL_SOCKET, ctls[0].level)
-	  assert_equal(Socket::SCM_RIGHTS, ctls[0].type)
-	  assert_instance_of(String, ctls[0].data)
-	  fd, rest = ctls[0].data.unpack("i!a*")
-	  assert_equal("", rest)
-	  r2 = IO.new(fd)
+          ctl = ctls[0]
+	  assert_instance_of(Socket::AncillaryData, ctl)
+	  assert_equal(Socket::SOL_SOCKET, ctl.level)
+	  assert_equal(Socket::SCM_RIGHTS, ctl.type)
+	  assert_instance_of(String, ctl.data)
+          ios = ctl.rights
+          assert_equal(1, ios.length)
+	  r2 = ios[0]
 	  begin
 	    assert(File.identical?(r1, r2))
 	  ensure

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

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