mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* ext/socket/option.c (sockopt_s_byte): constructor of the sockopt
whose value's is byte. * ext/socket/option.c (sockopt_byte): getter for above. * ext/socket/option.c (inspect_byte): inspect for above. * ext/socket/option.c (sockopt_s_ip_multicast_loop): constructor of the sockopt whose optname is IP_MULTICAST_LOOP. * ext/socket/option.c (sockopt_ip_multicast_loop): getter for above. * ext/socket/option.c (sockopt_s_ip_multicast_ttl): constructor of the sockopt whose optname is IP_MULTICAST_TTL. * ext/socket/option.c (sockopt_ip_multicast_ttl): getter for above. * ext/socket/option.c (sockopt_inspect): use above. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41009 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
1db209763a
commit
a78e45b5fe
3 changed files with 242 additions and 0 deletions
21
ChangeLog
21
ChangeLog
|
@ -1,3 +1,24 @@
|
|||
Sat Jun 1 02:37:35 2013 NARUSE, Yui <naruse@ruby-lang.org>
|
||||
|
||||
* ext/socket/option.c (sockopt_s_byte): constructor of the sockopt
|
||||
whose value's is byte.
|
||||
|
||||
* ext/socket/option.c (sockopt_byte): getter for above.
|
||||
|
||||
* ext/socket/option.c (inspect_byte): inspect for above.
|
||||
|
||||
* ext/socket/option.c (sockopt_s_ip_multicast_loop): constructor of
|
||||
the sockopt whose optname is IP_MULTICAST_LOOP.
|
||||
|
||||
* ext/socket/option.c (sockopt_ip_multicast_loop): getter for above.
|
||||
|
||||
* ext/socket/option.c (sockopt_s_ip_multicast_ttl): constructor of
|
||||
the sockopt whose optname is IP_MULTICAST_TTL.
|
||||
|
||||
* ext/socket/option.c (sockopt_ip_multicast_ttl): getter for above.
|
||||
|
||||
* ext/socket/option.c (sockopt_inspect): use above.
|
||||
|
||||
Sat Jun 01 01:50:00 2013 Kenta Murata <mrkn@mrkn.jp>
|
||||
|
||||
* ext/bigdecimal/bigdecimal.c (BigDecimal_power): use rb_dbl2big
|
||||
|
|
|
@ -142,6 +142,50 @@ sockopt_data(VALUE self)
|
|||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Socket::Option.byte(family, level, optname, integer) => sockopt
|
||||
*
|
||||
* Creates a new Socket::Option object which contains a byte as data.
|
||||
*
|
||||
* The size and endian is dependent on the platform.
|
||||
*
|
||||
* p Socket::Option.byte(:INET, :SOCKET, :KEEPALIVE, 1)
|
||||
* #=> #<Socket::Option: INET SOCKET KEEPALIVE 1>
|
||||
*/
|
||||
static VALUE
|
||||
sockopt_s_byte(VALUE klass, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE vint)
|
||||
{
|
||||
int family = rsock_family_arg(vfamily);
|
||||
int level = rsock_level_arg(family, vlevel);
|
||||
int optname = rsock_optname_arg(family, level, voptname);
|
||||
unsigned char i = (unsigned char)NUM2CHR(vint);
|
||||
return rsock_sockopt_new(family, level, optname, rb_str_new((char*)&i, sizeof(i)));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* sockopt.byte => integer
|
||||
*
|
||||
* Returns the data in _sockopt_ as an byte.
|
||||
*
|
||||
* The size and endian is dependent on the platform.
|
||||
*
|
||||
* sockopt = Socket::Option.byte(:INET, :SOCKET, :KEEPALIVE, 1)
|
||||
* p sockopt.byte => 1
|
||||
*/
|
||||
static VALUE
|
||||
sockopt_byte(VALUE self)
|
||||
{
|
||||
unsigned char i;
|
||||
VALUE data = sockopt_data(self);
|
||||
StringValue(data);
|
||||
if (RSTRING_LEN(data) != sizeof(i))
|
||||
rb_raise(rb_eTypeError, "size differ. expected as sizeof(int)=%d but %ld",
|
||||
(int)sizeof(i), (long)RSTRING_LEN(data));
|
||||
return CHR2FIX(*RSTRING_PTR(data));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Socket::Option.int(family, level, optname, integer) => sockopt
|
||||
|
@ -294,6 +338,138 @@ sockopt_linger(VALUE self)
|
|||
return rb_assoc_new(vonoff, vsecs);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Socket::Option.ip_multicast_loop(integer) => sockopt
|
||||
*
|
||||
* Creates a new Socket::Option object for IP_MULTICAST_LOOP.
|
||||
*
|
||||
* The size is dependent on the platform.
|
||||
*
|
||||
* sockopt = Socket::Option.int(:INET, :IPPROTO_IP, :IP_MULTICAST_LOOP, 1)
|
||||
* p sockopt.int => 1
|
||||
*
|
||||
* p Socket::Option.ip_multicast_loop(10)
|
||||
* #=> #<Socket::Option: INET IP MULTICAST_LOOP 10>
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
sockopt_s_ip_multicast_loop(VALUE klass, VALUE value)
|
||||
{
|
||||
#if defined(IPPROTO_IP) && defined(IP_MULTICAST_LOOP)
|
||||
# ifdef __NetBSD__
|
||||
unsigned char i = NUM2CHR(rb_to_int(value));
|
||||
# else
|
||||
int i = NUM2INT(rb_to_int(value));
|
||||
# endif
|
||||
return rsock_sockopt_new(AF_INET, IPPROTO_IP, IP_MULTICAST_LOOP,
|
||||
rb_str_new((char*)&i, sizeof(i)));
|
||||
#else
|
||||
# error IPPROTO_IP or IP_MULTICAST_LOOP is not implemented
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* sockopt.ip_multicast_loop => integer
|
||||
*
|
||||
* Returns the ip_multicast_loop data in _sockopt_ as a integer.
|
||||
*
|
||||
* sockopt = Socket::Option.ip_multicast_loop(10)
|
||||
* p sockopt.ip_multicast_loop => 10
|
||||
*/
|
||||
static VALUE
|
||||
sockopt_ip_multicast_loop(VALUE self)
|
||||
{
|
||||
int family = NUM2INT(sockopt_family_m(self));
|
||||
int level = sockopt_level(self);
|
||||
int optname = sockopt_optname(self);
|
||||
|
||||
#if defined(IPPROTO_IP) && defined(IP_MULTICAST_LOOP)
|
||||
if (family == AF_INET && level == IPPROTO_IP && optname == IP_MULTICAST_LOOP) {
|
||||
# ifdef __NetBSD__
|
||||
return sockopt_byte(self);
|
||||
# else
|
||||
return sockopt_int(self);
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
rb_raise(rb_eTypeError, "ip_multicast_loop socket option expected");
|
||||
UNREACHABLE;
|
||||
}
|
||||
|
||||
#ifdef __NetBSD__
|
||||
# define inspect_ip_multicast_loop(a,b,c,d) inspect_byte(a,b,c,d)
|
||||
#else
|
||||
# define inspect_ip_multicast_loop(a,b,c,d) inspect_int(a,b,c,d)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Socket::Option.ip_multicast_ttl(integer) => sockopt
|
||||
*
|
||||
* Creates a new Socket::Option object for IP_MULTICAST_TTL.
|
||||
*
|
||||
* The size is dependent on the platform.
|
||||
*
|
||||
* p Socket::Option.ip_multicast_ttl(10)
|
||||
* #=> #<Socket::Option: INET IP MULTICAST_TTL 10>
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
sockopt_s_ip_multicast_ttl(VALUE klass, VALUE value)
|
||||
{
|
||||
#if defined(IPPROTO_IP) && defined(IP_MULTICAST_TTL)
|
||||
# ifdef __NetBSD__
|
||||
unsigned char i = NUM2CHR(rb_to_int(value));
|
||||
# else
|
||||
int i = NUM2INT(rb_to_int(value));
|
||||
# endif
|
||||
return rsock_sockopt_new(AF_INET, IPPROTO_IP, IP_MULTICAST_TTL,
|
||||
rb_str_new((char*)&i, sizeof(i)));
|
||||
#else
|
||||
# error IPPROTO_IP or IP_MULTICAST_TTL is not implemented
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* sockopt.ip_multicast_ttl => integer
|
||||
*
|
||||
* Returns the ip_multicast_ttl data in _sockopt_ as a integer.
|
||||
*
|
||||
* sockopt = Socket::Option.ip_multicast_ttl(10)
|
||||
* p sockopt.ip_multicast_ttl => 10
|
||||
*/
|
||||
static VALUE
|
||||
sockopt_ip_multicast_ttl(VALUE self)
|
||||
{
|
||||
int family = NUM2INT(sockopt_family_m(self));
|
||||
int level = sockopt_level(self);
|
||||
int optname = sockopt_optname(self);
|
||||
|
||||
#if defined(IPPROTO_IP) && defined(IP_MULTICAST_TTL)
|
||||
if (family == AF_INET && level == IPPROTO_IP && optname == IP_MULTICAST_TTL) {
|
||||
# ifdef __NetBSD__
|
||||
return sockopt_byte(self);
|
||||
# else
|
||||
return sockopt_int(self);
|
||||
# endif
|
||||
}
|
||||
/*
|
||||
defined(IP_MULTICAST_LOOP)
|
||||
*/
|
||||
#endif
|
||||
rb_raise(rb_eTypeError, "ip_multicast_ttl socket option expected");
|
||||
UNREACHABLE;
|
||||
}
|
||||
|
||||
#ifdef __NetBSD__
|
||||
# define inspect_ip_multicast_ttl(a,b,c,d) inspect_byte(a,b,c,d)
|
||||
#else
|
||||
# define inspect_ip_multicast_ttl(a,b,c,d) inspect_int(a,b,c,d)
|
||||
#endif
|
||||
|
||||
static int
|
||||
inspect_int(int level, int optname, VALUE data, VALUE ret)
|
||||
{
|
||||
|
@ -308,6 +484,18 @@ inspect_int(int level, int optname, VALUE data, VALUE ret)
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
inspect_byte(int level, int optname, VALUE data, VALUE ret)
|
||||
{
|
||||
if (RSTRING_LEN(data) == sizeof(unsigned char)) {
|
||||
rb_str_catf(ret, " %d", (unsigned char)*RSTRING_PTR(data));
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
inspect_errno(int level, int optname, VALUE data, VALUE ret)
|
||||
{
|
||||
|
@ -804,6 +992,12 @@ sockopt_inspect(VALUE self)
|
|||
# endif
|
||||
# if defined(IP_DROP_MEMBERSHIP) /* 4.4BSD, GNU/Linux */
|
||||
case IP_DROP_MEMBERSHIP: inspected = inspect_ipv4_add_drop_membership(level, optname, data, ret); break;
|
||||
# endif
|
||||
# if defined(IP_MULTICAST_LOOP) /* 4.4BSD, GNU/Linux */
|
||||
case IP_MULTICAST_LOOP: inspected = inspect_ip_multicast_loop(level, optname, data, ret); break;
|
||||
# endif
|
||||
# if defined(IP_MULTICAST_TTL) /* 4.4BSD, GNU/Linux */
|
||||
case IP_MULTICAST_TTL: inspected = inspect_ip_multicast_ttl(level, optname, data, ret); break;
|
||||
# endif
|
||||
}
|
||||
break;
|
||||
|
@ -912,12 +1106,21 @@ rsock_init_sockopt(void)
|
|||
rb_define_singleton_method(rb_cSockOpt, "int", sockopt_s_int, 4);
|
||||
rb_define_method(rb_cSockOpt, "int", sockopt_int, 0);
|
||||
|
||||
rb_define_singleton_method(rb_cSockOpt, "byte", sockopt_s_byte, 4);
|
||||
rb_define_method(rb_cSockOpt, "byte", sockopt_byte, 0);
|
||||
|
||||
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_singleton_method(rb_cSockOpt, "ip_multicast_ttl", sockopt_s_ip_multicast_ttl, 1);
|
||||
rb_define_method(rb_cSockOpt, "ip_multicast_ttl", sockopt_ip_multicast_ttl, 0);
|
||||
|
||||
rb_define_singleton_method(rb_cSockOpt, "ip_multicast_loop", sockopt_s_ip_multicast_loop, 1);
|
||||
rb_define_method(rb_cSockOpt, "ip_multicast_loop", sockopt_ip_multicast_loop, 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 */
|
||||
|
|
|
@ -25,6 +25,24 @@ class TestSocketOption < Test::Unit::TestCase
|
|||
assert_equal(true, opt.bool)
|
||||
end
|
||||
|
||||
def test_ip_multicast_loop
|
||||
sockopt = Socket::Option.ip_multicast_loop(128)
|
||||
assert_equal('#<Socket::Option: INET IP MULTICAST_LOOP 128>', sockopt.inspect)
|
||||
assert_equal(Socket::AF_INET, sockopt.family)
|
||||
assert_equal(Socket::IPPROTO_IP, sockopt.level)
|
||||
assert_equal(Socket::IP_MULTICAST_LOOP, sockopt.optname)
|
||||
assert_equal(128, sockopt.ip_multicast_loop)
|
||||
end
|
||||
|
||||
def test_ip_multicast_ttl
|
||||
sockopt = Socket::Option.ip_multicast_ttl(128)
|
||||
assert_equal('#<Socket::Option: INET IP MULTICAST_TTL 128>', sockopt.inspect)
|
||||
assert_equal(Socket::AF_INET, sockopt.family)
|
||||
assert_equal(Socket::IPPROTO_IP, sockopt.level)
|
||||
assert_equal(Socket::IP_MULTICAST_TTL, sockopt.optname)
|
||||
assert_equal(128, sockopt.ip_multicast_ttl)
|
||||
end
|
||||
|
||||
def test_unpack
|
||||
sockopt = Socket::Option.new(:INET, :SOCKET, :KEEPALIVE, [1].pack("i"))
|
||||
assert_equal([1], sockopt.unpack("i"))
|
||||
|
|
Loading…
Reference in a new issue