mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* ext/socket/option.c (sockopt_level): extracted from sockopt_level_m.
(sockopt_optname): extracted from sockopt_optname_m. (sockopt_data): apply StringValue. (sockopt_s_linger): new method. (sockopt_linger): new method. (inspect_linger): show onoff value if it is neither 0 nor 1. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22634 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
1ff020df70
commit
e6f0b1de89
3 changed files with 113 additions and 4 deletions
|
@ -1,3 +1,12 @@
|
|||
Thu Feb 26 00:21:21 2009 Tanaka Akira <akr@fsij.org>
|
||||
|
||||
* ext/socket/option.c (sockopt_level): extracted from sockopt_level_m.
|
||||
(sockopt_optname): extracted from sockopt_optname_m.
|
||||
(sockopt_data): apply StringValue.
|
||||
(sockopt_s_linger): new method.
|
||||
(sockopt_linger): new method.
|
||||
(inspect_linger): show onoff value if it is neither 0 nor 1.
|
||||
|
||||
Wed Feb 25 23:23:03 2009 Tanaka Akira <akr@fsij.org>
|
||||
|
||||
* ext/socket/ancdata.c (ancillary_unix_rights): raise
|
||||
|
|
|
@ -83,6 +83,12 @@ sockopt_family_m(VALUE self)
|
|||
return rb_attr_get(self, rb_intern("family"));
|
||||
}
|
||||
|
||||
static int
|
||||
sockopt_level(VALUE self)
|
||||
{
|
||||
return NUM2INT(rb_attr_get(self, rb_intern("level")));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* sockopt.level => integer
|
||||
|
@ -95,7 +101,13 @@ sockopt_family_m(VALUE self)
|
|||
static VALUE
|
||||
sockopt_level_m(VALUE self)
|
||||
{
|
||||
return rb_attr_get(self, rb_intern("level"));
|
||||
return INT2NUM(sockopt_level(self));
|
||||
}
|
||||
|
||||
static int
|
||||
sockopt_optname(VALUE self)
|
||||
{
|
||||
return NUM2INT(rb_attr_get(self, rb_intern("optname")));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -110,7 +122,7 @@ sockopt_level_m(VALUE self)
|
|||
static VALUE
|
||||
sockopt_optname_m(VALUE self)
|
||||
{
|
||||
return rb_attr_get(self, rb_intern("optname"));
|
||||
return INT2NUM(sockopt_optname(self));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -125,7 +137,9 @@ sockopt_optname_m(VALUE self)
|
|||
static VALUE
|
||||
sockopt_data(VALUE self)
|
||||
{
|
||||
return rb_attr_get(self, rb_intern("data"));
|
||||
VALUE v = rb_attr_get(self, rb_intern("data"));
|
||||
StringValue(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -219,6 +233,67 @@ sockopt_bool(VALUE self)
|
|||
return i == 0 ? Qfalse : Qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Socket::Option.linger(onoff, secs) => sockopt
|
||||
*
|
||||
* Creates a new Socket::Option object for SOL_SOCKET/SO_LINGER.
|
||||
*
|
||||
* _onoff_ should be an integer or a boolean.
|
||||
*
|
||||
* _secs_ should be the number of seconds.
|
||||
*
|
||||
* p Socket::Option.linger(true, 10)
|
||||
* #=> #<Socket::Option: UNSPEC SOCKET LINGER on 10sec>
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
sockopt_s_linger(VALUE klass, VALUE vonoff, VALUE vsecs)
|
||||
{
|
||||
VALUE tmp;
|
||||
struct linger l;
|
||||
memset(&l, 0, sizeof(l));
|
||||
if (!NIL_P(tmp = rb_check_to_integer(vonoff, "to_int")))
|
||||
l.l_onoff = NUM2INT(tmp);
|
||||
else
|
||||
l.l_onoff = RTEST(vonoff) ? 1 : 0;
|
||||
l.l_linger = NUM2INT(vsecs);
|
||||
return sockopt_new(AF_UNSPEC, SOL_SOCKET, SO_LINGER, rb_str_new((char*)&l, sizeof(l)));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* sockopt.linger => [bool, seconds]
|
||||
*
|
||||
* Returns the linger data in _sockopt_ as a pair of boolean and integer.
|
||||
*
|
||||
* sockopt = Socket::Option.linger(true, 10)
|
||||
* p sockopt.linger => [true, 10]
|
||||
*/
|
||||
static VALUE
|
||||
sockopt_linger(VALUE self)
|
||||
{
|
||||
int level = sockopt_level(self);
|
||||
int optname = sockopt_optname(self);
|
||||
VALUE data = sockopt_data(self);
|
||||
struct linger l;
|
||||
VALUE vonoff, vsecs;
|
||||
|
||||
if (level != SOL_SOCKET || optname != SO_LINGER)
|
||||
rb_raise(rb_eTypeError, "linger socket option expected");
|
||||
if (RSTRING_LEN(data) != sizeof(l))
|
||||
rb_raise(rb_eTypeError, "size differ. expected as sizeof(struct linger)=%d but %ld",
|
||||
(int)sizeof(struct linger), (long)RSTRING_LEN(data));
|
||||
memcpy((char*)&l, RSTRING_PTR(data), sizeof(struct linger));
|
||||
switch (l.l_onoff) {
|
||||
case 0: vonoff = Qfalse; break;
|
||||
case 1: vonoff = Qtrue; break;
|
||||
default: vonoff = INT2NUM(l.l_onoff); break;
|
||||
}
|
||||
vsecs = INT2NUM(l.l_linger);
|
||||
return rb_assoc_new(vonoff, vsecs);
|
||||
}
|
||||
|
||||
static int
|
||||
inspect_int(int level, int optname, VALUE data, VALUE ret)
|
||||
{
|
||||
|
@ -272,7 +347,12 @@ inspect_linger(int level, int optname, VALUE data, VALUE ret)
|
|||
if (RSTRING_LEN(data) == sizeof(struct linger)) {
|
||||
struct linger s;
|
||||
memcpy((char*)&s, RSTRING_PTR(data), sizeof(s));
|
||||
rb_str_catf(ret, " %s %dsec", s.l_onoff ? "on" : "off", s.l_linger);
|
||||
switch (s.l_onoff) {
|
||||
case 0: rb_str_cat2(ret, " off"); break;
|
||||
case 1: rb_str_cat2(ret, " on"); break;
|
||||
default: rb_str_catf(ret, " on(%d)", s.l_onoff); break;
|
||||
}
|
||||
rb_str_catf(ret, " %dsec", s.l_linger);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
|
@ -598,6 +678,9 @@ Init_sockopt(void)
|
|||
rb_define_singleton_method(rb_cSockOpt, "bool", sockopt_s_bool, 4);
|
||||
rb_define_method(rb_cSockOpt, "bool", sockopt_bool, 0);
|
||||
|
||||
rb_define_singleton_method(rb_cSockOpt, "linger", sockopt_s_linger, 2);
|
||||
rb_define_method(rb_cSockOpt, "linger", sockopt_linger, 0);
|
||||
|
||||
rb_define_method(rb_cSockOpt, "unpack", sockopt_unpack, 1);
|
||||
|
||||
rb_define_method(rb_cSockOpt, "to_s", sockopt_data, 0); /* compatibility for ruby before 1.9.2 */
|
||||
|
|
|
@ -273,6 +273,23 @@ class TestSocket < Test::Unit::TestCase
|
|||
}
|
||||
end
|
||||
|
||||
def test_linger
|
||||
opt = Socket::Option.linger(true, 0)
|
||||
assert_equal([true, 0], opt.linger)
|
||||
Addrinfo.tcp("127.0.0.1", 0).listen {|serv|
|
||||
serv.local_address.connect {|s1|
|
||||
s2, _ = serv.accept
|
||||
begin
|
||||
s1.setsockopt(opt)
|
||||
s1.close
|
||||
assert_raise(Errno::ECONNRESET) { s2.read }
|
||||
ensure
|
||||
s2.close
|
||||
end
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_timestamp
|
||||
return if /linux|freebsd|netbsd|openbsd|solaris|darwin/ !~ RUBY_PLATFORM
|
||||
t1 = Time.now.strftime("%Y-%m-%d")
|
||||
|
|
Loading…
Reference in a new issue