Class: Socket::Option
- Inherits:
-
Object
- Object
- Socket::Option
- Defined in:
- option.c,
option.c
Overview
Socket::Option represents a socket option used by BasicSocket#getsockopt and BasicSocket#setsockopt. A socket option contains the socket #family, protocol #level, option name #optname and option value #data.
Class Method Summary collapse
-
.Socket::Option.bool(family, level, optname, bool) ⇒ Object
Creates a new Socket::Option object which contains boolean as data.
-
.Socket::Option.byte(family, level, optname, integer) ⇒ Object
Creates a new Socket::Option object which contains a byte as data.
-
.Socket::Option.int(family, level, optname, integer) ⇒ Object
Creates a new Socket::Option object which contains an int as data.
-
.Socket::Option.ipv4_multicast_loop(integer) ⇒ Object
Creates a new Socket::Option object for IP_MULTICAST_LOOP.
-
.Socket::Option.ipv4_multicast_ttl(integer) ⇒ Object
Creates a new Socket::Option object for IP_MULTICAST_TTL.
-
.Socket::Option.linger(onoff, secs) ⇒ Object
Creates a new Socket::Option object for SOL_SOCKET/SO_LINGER.
Instance Method Summary collapse
-
#bool ⇒ Boolean
Returns the data in sockopt as an boolean value.
-
#byte ⇒ Integer
Returns the data in sockopt as an byte.
-
#data ⇒ Object
returns the socket option data as a string.
-
#family ⇒ Integer
returns the socket family as an integer.
-
#Socket::Option.new(family, level, optname, data) ⇒ Object
constructor
Returns a new Socket::Option object.
-
#inspect ⇒ String
Returns a string which shows sockopt in human-readable form.
-
#int ⇒ Integer
Returns the data in sockopt as an int.
-
#ipv4_multicast_loop ⇒ Integer
Returns the ipv4_multicast_loop data in sockopt as a integer.
-
#ipv4_multicast_ttl ⇒ Integer
Returns the ipv4_multicast_ttl data in sockopt as a integer.
-
#level ⇒ Integer
returns the socket level as an integer.
-
#linger ⇒ Array
Returns the linger data in sockopt as a pair of boolean and integer.
-
#optname ⇒ Integer
returns the socket option name as an integer.
-
#to_s ⇒ Object
returns the socket option data as a string.
-
#unpack(template) ⇒ Array
Calls String#unpack on sockopt.data.
Constructor Details
#Socket::Option.new(family, level, optname, data) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'option.c', line 47
static VALUE
sockopt_initialize(VALUE self, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE data)
{
int family = rsock_family_arg(vfamily);
int level = rsock_level_arg(family, vlevel);
int optname = rsock_optname_arg(family, level, voptname);
StringValue(data);
rb_ivar_set(self, rb_intern("family"), INT2NUM(family));
rb_ivar_set(self, rb_intern("level"), INT2NUM(level));
rb_ivar_set(self, rb_intern("optname"), INT2NUM(optname));
rb_ivar_set(self, rb_intern("data"), data);
return self;
}
|
Class Method Details
.Socket::Option.bool(family, level, optname, bool) ⇒ Object
Creates a new Socket::Option object which contains boolean as data. Actually 0 or 1 as int is used.
p Socket::Option.bool(:INET, :SOCKET, :KEEPALIVE, true)
#=> #<Socket::Option: INET SOCKET KEEPALIVE 1>
p Socket::Option.bool(:INET, :SOCKET, :KEEPALIVE, false)
#=> #<Socket::Option: AF_INET SOCKET KEEPALIVE 0>
248 249 250 251 252 253 254 255 256 |
# File 'option.c', line 248
static VALUE
sockopt_s_bool(VALUE klass, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE vbool)
{
int family = rsock_family_arg(vfamily);
int level = rsock_level_arg(family, vlevel);
int optname = rsock_optname_arg(family, level, voptname);
int i = RTEST(vbool) ? 1 : 0;
return rsock_sockopt_new(family, level, optname, rb_str_new((char*)&i, sizeof(i)));
}
|
.Socket::Option.byte(family, level, optname, integer) ⇒ Object
156 157 158 159 160 161 162 163 164 |
# File 'option.c', line 156
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)));
}
|
.Socket::Option.int(family, level, optname, integer) ⇒ Object
200 201 202 203 204 205 206 207 208 |
# File 'option.c', line 200
static VALUE
sockopt_s_int(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);
int i = NUM2INT(vint);
return rsock_sockopt_new(family, level, optname, rb_str_new((char*)&i, sizeof(i)));
}
|
.Socket::Option.ipv4_multicast_loop(integer) ⇒ Object
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 |
# File 'option.c', line 356
static VALUE
sockopt_s_ipv4_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
}
|
.Socket::Option.ipv4_multicast_ttl(integer) ⇒ Object
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 |
# File 'option.c', line 419
static VALUE
sockopt_s_ipv4_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
}
|
.Socket::Option.linger(onoff, secs) ⇒ Object
294 295 296 297 298 299 300 301 302 303 304 305 306 |
# File 'option.c', line 294
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 rsock_sockopt_new(AF_UNSPEC, SOL_SOCKET, SO_LINGER, rb_str_new((char*)&l, sizeof(l)));
}
|
Instance Method Details
#bool ⇒ Boolean
267 268 269 270 271 272 273 274 275 276 277 278 |
# File 'option.c', line 267
static VALUE
sockopt_bool(VALUE self)
{
int i;
VALUE data = sockopt_data(self);
StringValue(data);
if (RSTRING_LEN(data) != sizeof(int))
rb_raise(rb_eTypeError, "size differ. expected as sizeof(int)=%d but %ld",
(int)sizeof(int), (long)RSTRING_LEN(data));
memcpy((char*)&i, RSTRING_PTR(data), sizeof(int));
return i == 0 ? Qfalse : Qtrue;
}
|
#byte ⇒ Integer
177 178 179 180 181 182 183 184 185 186 187 |
# File 'option.c', line 177
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));
}
|
#data ⇒ String #to_s ⇒ String
137 138 139 140 141 142 143 |
# File 'option.c', line 137
static VALUE
sockopt_data(VALUE self)
{
VALUE v = rb_attr_get(self, rb_intern("data"));
StringValue(v);
return v;
}
|
#family ⇒ Integer
79 80 81 82 83 |
# File 'option.c', line 79
static VALUE
sockopt_family_m(VALUE self)
{
return rb_attr_get(self, rb_intern("family"));
}
|
#inspect ⇒ String
854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 |
# File 'option.c', line 854
static VALUE
sockopt_inspect(VALUE self)
{
int family = NUM2INT(sockopt_family_m(self));
int level = NUM2INT(sockopt_level_m(self));
int optname = NUM2INT(sockopt_optname_m(self));
VALUE data = sockopt_data(self);
VALUE v, ret;
ID family_id, level_id, optname_id;
int inspected;
StringValue(data);
ret = rb_sprintf("#<%s:", rb_obj_classname(self));
family_id = rsock_intern_family_noprefix(family);
if (family_id)
rb_str_catf(ret, " %s", rb_id2name(family_id));
else
rb_str_catf(ret, " family:%d", family);
if (level == SOL_SOCKET) {
rb_str_cat2(ret, " SOCKET");
optname_id = rsock_intern_so_optname(optname);
if (optname_id)
rb_str_catf(ret, " %s", rb_id2name(optname_id));
else
rb_str_catf(ret, " optname:%d", optname);
}
#ifdef HAVE_SYS_UN_H
else if (family == AF_UNIX) {
rb_str_catf(ret, " level:%d", level);
optname_id = rsock_intern_local_optname(optname);
if (optname_id)
rb_str_catf(ret, " %s", rb_id2name(optname_id));
else
rb_str_catf(ret, " optname:%d", optname);
}
#endif
else if (IS_IP_FAMILY(family)) {
level_id = rsock_intern_iplevel(level);
if (level_id)
rb_str_catf(ret, " %s", rb_id2name(level_id));
else
rb_str_catf(ret, " level:%d", level);
v = optname_to_sym(level, optname);
if (SYMBOL_P(v))
rb_str_catf(ret, " %s", rb_id2name(SYM2ID(v)));
else
rb_str_catf(ret, " optname:%d", optname);
}
else {
rb_str_catf(ret, " level:%d", level);
rb_str_catf(ret, " optname:%d", optname);
}
inspected = 0;
if (level == SOL_SOCKET)
family = AF_UNSPEC;
switch (family) {
case AF_UNSPEC:
switch (level) {
case SOL_SOCKET:
switch (optname) {
# if defined(SO_DEBUG) /* POSIX */
case SO_DEBUG: inspected = inspect_int(level, optname, data, ret); break;
# endif
# if defined(SO_ERROR) /* POSIX */
case SO_ERROR: inspected = inspect_errno(level, optname, data, ret); break;
# endif
# if defined(SO_TYPE) /* POSIX */
case SO_TYPE: inspected = inspect_socktype(level, optname, data, ret); break;
# endif
# if defined(SO_ACCEPTCONN) /* POSIX */
case SO_ACCEPTCONN: inspected = inspect_int(level, optname, data, ret); break;
# endif
# if defined(SO_BROADCAST) /* POSIX */
case SO_BROADCAST: inspected = inspect_int(level, optname, data, ret); break;
# endif
# if defined(SO_REUSEADDR) /* POSIX */
case SO_REUSEADDR: inspected = inspect_int(level, optname, data, ret); break;
# endif
# if defined(SO_KEEPALIVE) /* POSIX */
case SO_KEEPALIVE: inspected = inspect_int(level, optname, data, ret); break;
# endif
# if defined(SO_OOBINLINE) /* POSIX */
case SO_OOBINLINE: inspected = inspect_int(level, optname, data, ret); break;
# endif
# if defined(SO_SNDBUF) /* POSIX */
case SO_SNDBUF: inspected = inspect_int(level, optname, data, ret); break;
# endif
# if defined(SO_RCVBUF) /* POSIX */
case SO_RCVBUF: inspected = inspect_int(level, optname, data, ret); break;
# endif
# if defined(SO_DONTROUTE) /* POSIX */
case SO_DONTROUTE: inspected = inspect_int(level, optname, data, ret); break;
# endif
# if defined(SO_RCVLOWAT) /* POSIX */
case SO_RCVLOWAT: inspected = inspect_int(level, optname, data, ret); break;
# endif
# if defined(SO_SNDLOWAT) /* POSIX */
case SO_SNDLOWAT: inspected = inspect_int(level, optname, data, ret); break;
# endif
# if defined(SO_LINGER) /* POSIX */
case SO_LINGER: inspected = inspect_linger(level, optname, data, ret); break;
# endif
# if defined(SO_RCVTIMEO) /* POSIX */
case SO_RCVTIMEO: inspected = inspect_timeval_as_interval(level, optname, data, ret); break;
# endif
# if defined(SO_SNDTIMEO) /* POSIX */
case SO_SNDTIMEO: inspected = inspect_timeval_as_interval(level, optname, data, ret); break;
# endif
# if defined(SO_PEERCRED) /* GNU/Linux, OpenBSD */
case SO_PEERCRED: inspected = inspect_peercred(level, optname, data, ret); break;
# endif
}
break;
}
break;
case AF_INET:
#ifdef INET6
case AF_INET6:
#endif
switch (level) {
# if defined(IPPROTO_IP)
case IPPROTO_IP:
switch (optname) {
# if defined(IP_MULTICAST_IF) && defined(HAVE_TYPE_STRUCT_IP_MREQN) /* 4.4BSD, GNU/Linux */
case IP_MULTICAST_IF: inspected = inspect_ipv4_multicast_if(level, optname, data, ret); break;
# endif
# if defined(IP_ADD_MEMBERSHIP) /* 4.4BSD, GNU/Linux */
case IP_ADD_MEMBERSHIP: inspected = inspect_ipv4_add_drop_membership(level, optname, data, ret); break;
# 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_ipv4_multicast_loop(level, optname, data, ret); break;
# endif
# if defined(IP_MULTICAST_TTL) /* 4.4BSD, GNU/Linux */
case IP_MULTICAST_TTL: inspected = inspect_ipv4_multicast_ttl(level, optname, data, ret); break;
# endif
}
break;
# endif
# if defined(IPPROTO_IPV6)
case IPPROTO_IPV6:
switch (optname) {
# if defined(IPV6_MULTICAST_HOPS) /* POSIX */
case IPV6_MULTICAST_HOPS: inspected = inspect_int(level, optname, data, ret); break;
# endif
# if defined(IPV6_MULTICAST_IF) /* POSIX */
case IPV6_MULTICAST_IF: inspected = inspect_ipv6_multicast_if(level, optname, data, ret); break;
# endif
# if defined(IPV6_MULTICAST_LOOP) /* POSIX */
case IPV6_MULTICAST_LOOP: inspected = inspect_uint(level, optname, data, ret); break;
# endif
# if defined(IPV6_JOIN_GROUP) /* POSIX */
case IPV6_JOIN_GROUP: inspected = inspect_ipv6_mreq(level, optname, data, ret); break;
# endif
# if defined(IPV6_LEAVE_GROUP) /* POSIX */
case IPV6_LEAVE_GROUP: inspected = inspect_ipv6_mreq(level, optname, data, ret); break;
# endif
# if defined(IPV6_UNICAST_HOPS) /* POSIX */
case IPV6_UNICAST_HOPS: inspected = inspect_int(level, optname, data, ret); break;
# endif
# if defined(IPV6_V6ONLY) /* POSIX */
case IPV6_V6ONLY: inspected = inspect_int(level, optname, data, ret); break;
# endif
}
break;
# endif
# if defined(IPPROTO_TCP)
case IPPROTO_TCP:
switch (optname) {
# if defined(TCP_NODELAY) /* POSIX */
case TCP_NODELAY: inspected = inspect_int(level, optname, data, ret); break;
# endif
}
break;
# endif
}
break;
#ifdef HAVE_SYS_UN_H
case AF_UNIX:
switch (level) {
case 0:
switch (optname) {
# if defined(LOCAL_PEERCRED)
case LOCAL_PEERCRED: inspected = inspect_local_peercred(level, optname, data, ret); break;
# endif
}
break;
}
break;
#endif
}
if (!inspected) {
rb_str_cat2(ret, " ");
rb_str_append(ret, rb_str_dump(data));
}
rb_str_cat2(ret, ">");
return ret;
}
|
#int ⇒ Integer
221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'option.c', line 221
static VALUE
sockopt_int(VALUE self)
{
int i;
VALUE data = sockopt_data(self);
StringValue(data);
if (RSTRING_LEN(data) != sizeof(int))
rb_raise(rb_eTypeError, "size differ. expected as sizeof(int)=%d but %ld",
(int)sizeof(int), (long)RSTRING_LEN(data));
memcpy((char*)&i, RSTRING_PTR(data), sizeof(int));
return INT2NUM(i);
}
|
#ipv4_multicast_loop ⇒ Integer
Returns the ipv4_multicast_loop data in sockopt as a integer.
sockopt = Socket::Option.ipv4_multicast_loop(10)
p sockopt.ipv4_multicast_loop => 10
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 |
# File 'option.c', line 381
static VALUE
sockopt_ipv4_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, "ipv4_multicast_loop socket option expected");
UNREACHABLE;
}
|
#ipv4_multicast_ttl ⇒ Integer
Returns the ipv4_multicast_ttl data in sockopt as a integer.
sockopt = Socket::Option.ipv4_multicast_ttl(10)
p sockopt.ipv4_multicast_ttl => 10
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 |
# File 'option.c', line 444
static VALUE
sockopt_ipv4_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
}
#endif
rb_raise(rb_eTypeError, "ipv4_multicast_ttl socket option expected");
UNREACHABLE;
}
|
#level ⇒ Integer
100 101 102 103 104 |
# File 'option.c', line 100
static VALUE
sockopt_level_m(VALUE self)
{
return INT2NUM(sockopt_level(self));
}
|
#linger ⇒ Array
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 |
# File 'option.c', line 317
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);
}
|
#optname ⇒ Integer
121 122 123 124 125 |
# File 'option.c', line 121
static VALUE
sockopt_optname_m(VALUE self)
{
return INT2NUM(sockopt_optname(self));
}
|
#data ⇒ String #to_s ⇒ String
137 138 139 140 141 142 143 |
# File 'option.c', line 137
static VALUE
sockopt_data(VALUE self)
{
VALUE v = rb_attr_get(self, rb_intern("data"));
StringValue(v);
return v;
}
|
#unpack(template) ⇒ Array
1080 1081 1082 1083 1084 |
# File 'option.c', line 1080
static VALUE
sockopt_unpack(VALUE self, VALUE template)
{
return rb_funcall(sockopt_data(self), rb_intern("unpack"), 1, template);
}
|