summaryrefslogtreecommitdiff
path: root/ext/socket
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-02-24 10:45:46 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-02-24 10:45:46 +0000
commitb404c651d2e732fa25e0c009892682a7718d0d2a (patch)
treeedd1c1aefb4ed803cd79e98931967d7f58c3775a /ext/socket
parent96322412616091404ffef2687df19e9136119ae0 (diff)
* ext/socket/ancdata.c (ancillary_timestamp): new method.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22593 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/socket')
-rw-r--r--ext/socket/ancdata.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/ext/socket/ancdata.c b/ext/socket/ancdata.c
index 9ecca28b9e..0761db6787 100644
--- a/ext/socket/ancdata.c
+++ b/ext/socket/ancdata.c
@@ -202,6 +202,65 @@ ancillary_unix_rights(VALUE self)
/*
* call-seq:
+ * ancillarydata.timestamp => time
+ *
+ * returns the timestamp as a time object.
+ *
+ * _ancillarydata_ should be one of following type:
+ * - SOL_SOCKET/SCM_TIMESTAMP (micro second) GNU/Linux, FreeBSD, NetBSD, OpenBSD, Solaris, MacOS X
+ * - SOL_SOCKET/SCM_TIMESTAMPNS (nano second) GNU/Linux
+ *
+ * Addrinfo.udp("127.0.0.1", 0).bind {|s1|
+ * Addrinfo.udp("127.0.0.1", 0).bind {|s2|
+ * s1.setsockopt(:SOCKET, :TIMESTAMP, true)
+ * s2.send "a", 0, s1.local_address
+ * ctl = s1.recvmsg.last
+ * p ctl #=> #<Socket::AncillaryData: INET SOCKET TIMESTAMP 2009-02-24 17:35:46.775581>
+ * t = ctl.timestamp
+ * p t #=> 2009-02-24 17:35:46 +0900
+ * p t.usec #=> 775581
+ * p t.nsec #=> 775581000
+ * }
+ * }
+ *
+ */
+static VALUE
+ancillary_timestamp(VALUE self)
+{
+ int level, type;
+ VALUE data;
+ VALUE result = Qnil;
+
+ level = ancillary_level(self);
+ type = ancillary_type(self);
+ data = ancillary_data(self);
+
+#ifdef SCM_TIMESTAMP
+ if (level == SOL_SOCKET && type == SCM_TIMESTAMP &&
+ RSTRING_LEN(data) == sizeof(struct timeval)) {
+ struct timeval tv;
+ memcpy((char*)&tv, RSTRING_PTR(data), sizeof(tv));
+ result = rb_time_new(tv.tv_sec, tv.tv_usec);
+ }
+#endif
+
+#ifdef SCM_TIMESTAMPNS
+ if (level == SOL_SOCKET && type == SCM_TIMESTAMPNS &&
+ RSTRING_LEN(data) == sizeof(struct timespec)) {
+ struct timespec ts;
+ memcpy((char*)&ts, RSTRING_PTR(data), sizeof(ts));
+ result = rb_time_nano_new(ts.tv_sec, ts.tv_nsec);
+ }
+#endif
+
+ if (result == Qnil)
+ rb_raise(rb_eTypeError, "timestamp ancillary data expected");
+
+ return result;
+}
+
+/*
+ * call-seq:
* Socket::AncillaryData.int(family, cmsg_level, cmsg_type, integer) => ancillarydata
*
* Creates a new Socket::AncillaryData object which contains a int as data.
@@ -1597,6 +1656,7 @@ Init_ancdata(void)
rb_define_method(rb_cAncillaryData, "type", ancillary_type_m, 0);
rb_define_method(rb_cAncillaryData, "data", ancillary_data, 0);
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);