1
0
Fork 0
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:
naruse 2013-05-31 17:37:55 +00:00
parent 1db209763a
commit a78e45b5fe
3 changed files with 242 additions and 0 deletions

View file

@ -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

View file

@ -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 */

View file

@ -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"))