# Socket::Option

**URL:** <https://www.ruby-forum.com/t/socket-option/158053>\
**Category:** Development\
**Created:** [January 18, 2009, 5:13pm UTC](https://www.ruby-forum.com/t/socket-option/158053 "2009-01-18T17:13:54Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tanaka\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c67d28/32.png) [@Tanaka\_A](https://www.ruby-forum.com/u/Tanaka_A)\
**Post date:** [January 18, 2009, 5:13pm UTC](https://www.ruby-forum.com/t/socket-option/158053/1 "2009-01-18T17:13:54Z")

</div>

e$BDs0F$J$s$G$9$,!"e(BSocket::Option e$B%/%i%9$r:n$C$F!"e(B  
BasicSocket#getsockopt e$B$,e(B Socket::Option  
e$B%$%s%9%?%s%9$rJV$7!"e(B  
BasicSocket#setsockopt e$B$,e(B Socket::Option e$B%$%s%9%?%s%9$r\<u$1e(B  
e$BIU$1$k$h$&$K$9$k$N$O$I$&$G$7$g$&$+!#e(B

e$B8=:\_!“e(Bgetsockopt e$B$O%P%$%J%j$Ne(B string  
e$B$rJV$7$^$9$,!”$3$l$O$oe(B  
e$B$+$j$d$9$$$b$N$H$O$$$($^$;$s!#e(B

e$B$?$H$($P!"0J2\<$NNc$O!“e(BSOL\_SOCKET e$B$Ne(B SO\_TYPE  
e$B$H$$$&$N$rLd$$9ge(B  
e$B$o$;$?$b$N$G$9$,!“e(B”\x02\x00\x00\x00” e$B$H$$$&7k2L$,2?$r0UL#$7e(B  
e$B$F$$$k$+$O$h$/$o$+$j$^$;$s!#e(B

% ruby -rsocket -e ’  
s = Socket.new(Socket::PF\_INET, Socket::SOCK\_DGRAM, 0)  
p s.getsockopt(Socket::SOL\_SOCKET, Socket::SO\_TYPE)’  
“\x02\x00\x00\x00”

e$B$3$3$G!"e(Bgetsockopt e$B$,e(B string  
e$B$G$J$/!“FH\<+$N%/%i%9$N%_%V%8%'e(B  
e$B%/%H$rJV$9$3$H$K$9$l$P!“e(B(e$B$”$He(B SOL\_SOCKET e$B$He(B SO\_TYPE  
e$B$H$$$&$Ne(B  
e$B$r%_%V%8%’%/%H$K5-O?$7$F$\*$1$Pe(B) inspect e$B$rE,@Z$K\<BAu$9$k$3$He(B  
e$B$K$h$j!”$o$+$j$d$9$/I=\<($9$k$3$H$,$G$-$^$9!#$3$N\>l9g$O!"e(B  
SOCK\_DGRAM e$B$H$$$&L\>A0$rI=\<($G$-$^$9!#e(B

% ./ruby -rsocket -e ’  
s = Socket.new(Socket::PF\_INET, Socket::SOCK\_DGRAM, 0)  
p s.getsockopt(Socket::SOL\_SOCKET, Socket::SO\_TYPE)’  
#\<Socket::Option: SOCKET TYPE SOCK\_DGRAM\>

e$B$^$?!“e(Binspect e$B$@$1$G$J$/!”%G!\<%?$NCf?H$r\<h$j=P$9%a%=%C%I$b$De(B  
e$B$1$i$l$^$9!#e(B

e$B\>e5-$Ne(B “\x02\x00\x00\x00” e$B$Oe(B SOCK\_DGRAM  
e$B$G$9$,!"$=$NCM$r\<h$je(B  
e$B=P$9$K$O!"e(Bsockopt.unpack(“i”)[0] e$B$H$7$J$$$H$$$1$^$;$s!#e(B  
Socket::Option#int e$B$K$h$j!"e(Bsockopt.int e$B$G:Q$^$;$i$l$^$9!#e(B

e$B$^$?!"@8@.$9$k$[$&$b4JC1$K$J$j$^$9!#e(B  
e$B\>e5-$N$h$&$Je(B int e$B$N$b$N$G$"$l$P!“e(B[opt].pack(“i”)  
e$B$G:Q$`$N$Ge(B  
e$B$=$s$J$KBgJQ$G$O$”$j$^$;$s$,!"%=%1%C%H%\*%W%7%g%s$OI,$:$7$be(B  
int e$B$P$+$j$G$O$"$j$^$;$s!#e(B

SO\_LINGER e$B$@$H9=B$BN$G!“Cf$Ke(B int e$B$,$U$?$DJB$s$G$$$^$9!#5,3Je(B  
e$B$O=gHV$^$G$O7h$a$F$/$l$F$$$J$$$N$G!”=gHV$r$I$&$9$k$+$O%W%i%Ce(B  
e$B%H%U%)!\<%`0MB8$K$J$j$^$9!#e(B

SO\_SNDTIMEO e$B$de(B SO\_RCVTIMEO e$B$Oe(B struct timeval e$B$G!"Cf$Ke(B  
time\_t  
e$B$,F~$C$F$$$^$9$,!"e(Btime\_t e$B$N%5%$%:$O%W%i%C%H%U%)!\<%`$K0MB8$7e(B  
e$B$^$9!#e(B

e$B%^%k%A%-%c%9%H4X78$H$+$G$Oe(B IP e$B%"%I%l%9$rF~$l$J$$$H$$$1$J$$$3e(B  
e$B$H$b$"$j$^$9!#e(B

e$B$3$&$$$&9=B$BN$N07$$$O!"$d$O$je(B C e$B$G=q$$$?$[$&$,3N\<B$G!“e(B  
Socket::Option.linger e$B$H$+!”%/%i%9%a%=%C%I$H$7$F@8@.%a%=%C%Ie(B  
e$B$r:n$j!“e(Bsetsockopt e$B$KEO$;$l$P4JC1$G$9!#e(B  
(e$B$H$j$”$($:8=;~E@$G$Oe(B Socket::Option.int e$B$7$+:n$C$F$^$;$s$,e(B)

BasicSocket#getsockopt e$B$OJV$9CM$,JQ$o$k$N$GHs8\_49$K$J$j$^$9e(B  
e$B$,!“BP:v$H$7$Fe(B SocketOption#unpack e$B$r\<BAu$7$F$”$j$^$9!#$D$^e(B  
e$B$j!“e(Bunpack e$B$r8F$S=P$98B$j$O8\_49$G!”$1$C$3$&5\_$($k$s$8$c$J$$e(B  
e$B$+$H;W$C$F$^$9!#$^$?!"$=$l$G$O:Q$^$J$$$H$-$K$O!"e(B  
Socket::Option#data e$B%a%=%C%I$Ge(B string e$B$J0JA0$NCM$,\<h$j=P$;$^e(B  
e$B$9!#e(B

e$B$H$$$&$o$1$G$I$&$G$7$g$&$+!#e(B

# Index: ext/.document

# — ext/.document (revision 21646) +++ ext/.document (working copy) @@ -20,6 +20,7 @@ socket/udpsocket.c socket/unixsocket.c socket/unixserver.c socket/socket.c +socket/option.c socket/constants.c socket/lib/socket.rb stringio/stringio.c Index: ext/socket/rubysocket.h

— ext/socket/rubysocket.h (revision 21646)  
+++ ext/socket/rubysocket.h (working copy)  
@@ -135,6 +135,7 @@ extern VALUE rb\_cUNIXServer;  
#endif  
extern VALUE rb\_cSocket;  
extern VALUE rb\_cAddrInfo;  
+extern VALUE rb\_cSockOpt;

extern VALUE rb\_eSocket;

@@ -214,6 +215,8 @@ VALUE sock\_listen(VALUE sock, VALUE log)  
VALUE s\_accept(VALUE klass, int fd, struct sockaddr \*sockaddr,  
socklen\_t \*len);  
VALUE s\_accept\_nonblock(VALUE klass, rb\_io\_t \*fptr, struct sockaddr  
\*sockaddr, socklen\_t \*len);

+VALUE sockopt\_new(int level, int optname, VALUE data);  
+  
void Init\_basicsocket(void);  
void Init\_ipsocket(void);  
void Init\_tcpsocket(void);  
@@ -224,6 +227,7 @@ void Init\_unixsocket(void);  
void Init\_unixserver(void);  
void Init\_socket\_constants(void);  
void Init\_addrinfo(void);  
+void Init\_sockopt(void);  
void Init\_socket\_init(void);

# #endif Index: ext/socket/init.c

— ext/socket/init.c (revision 21646)  
+++ ext/socket/init.c (working copy)  
@@ -510,6 +510,7 @@ Init\_socket\_init()  
Init\_udpsocket();  
Init\_unixsocket();  
Init\_unixserver();

- Init\_sockopt();  
Init\_addrinfo();  
Init\_socket\_constants();  
}  
Index: ext/socket/option.c  
===================================================================  
— ext/socket/option.c (revision 0)  
+++ ext/socket/option.c (revision 0)  
@@ -0,0 +1,373 @@  
+#include “rubysocket.h”
- 

+VALUE rb\_cSockOpt;  
+  
+static VALUE  
+constant\_to\_sym(int constant, ID (\*intern\_const)(int))  
+{

- ID name = intern\_const(constant);
- if (name) {
- 

```
   return ID2SYM(name);

```

- }
- 
- return INT2NUM(constant);  
+}
- 

+static VALUE  
+optname\_to\_sym(int level, int optname)  
+{

- switch (level) {
- 

```
 case SOL_SOCKET:

```

- 

```
   return constant_to_sym(optname, intern_so_optname);

```

- 

```
 case IPPROTO_IP:

```

- 

```
   return constant_to_sym(optname, intern_ip_optname);

```

- 

```
 case IPPROTO_IPV6:

```

- 

```
   return constant_to_sym(optname, intern_ipv6_optname);

```

- 

```
 case IPPROTO_TCP:

```

- 

```
   return constant_to_sym(optname, intern_tcp_optname);

```

- 

```
 case IPPROTO_UDP:

```

- 

```
   return constant_to_sym(optname, intern_udp_optname);

```

- 

```
 default:

```

- 

```
   return INT2NUM(optname);

```

- }  
+}
- 

+static VALUE  
+sockopt\_initialize(VALUE self, VALUE vlevel, VALUE voptname, VALUE  
data)  
+{

- int level;
- StringValue(data);
- level = level\_arg(vlevel);
- rb\_ivar\_set(self, rb\_intern(“level”), INT2NUM(level));
- rb\_ivar\_set(self, rb\_intern(“optname”), INT2NUM(optname\_arg(level,  
voptname)));
- rb\_ivar\_set(self, rb\_intern(“data”), data);
- return self;  
+}
- 

+VALUE  
+sockopt\_new(int level, int optname, VALUE data)  
+{

- NEWOBJ(obj, struct RObject);
- OBJSETUP(obj, rb\_cSockOpt, T\_OBJECT);
- StringValue(data);
- sockopt\_initialize((VALUE)obj, INT2NUM(level), INT2NUM(optname),  
data);
- return (VALUE)obj;  
+}
- 

+/\*

- 
  - call-seq:

- 
  - sockopt.level =\> integer

- 
  - 

- 
  - returns the socket level as an integer.

- 
  - 

- 
  - p Socket::Option.new(:IPV6, :RECVPKTINFO, [1].pack(“i!”)).level

- \*/  
+static VALUE  
+sockopt\_level(VALUE self)  
+{
- return rb\_attr\_get(self, rb\_intern(“level”));  
+}
- 

+/\*

- 
  - call-seq:

- 
  - sockopt.optname =\> integer

- 
  - 

- 
  - returns the socket option name as an integer.

- 
  - 

- 
  - p Socket::Option.new(:IPV6, :RECVPKTINFO, [1].pack(“i!”)).optname

- \*/  
+static VALUE  
+sockopt\_optname(VALUE self)  
+{
- return rb\_attr\_get(self, rb\_intern(“optname”));  
+}
- 

+/\*

- 
  - call-seq:

- 
  - sockopt.data =\> string

- 
  - 

- 
  - returns the socket option data as a string.

- 
  - 

- 
  - p Socket::Option.new(:IPV6, :PKTINFO, [1].pack(“i!”)).data

- \*/  
+static VALUE  
+sockopt\_data(VALUE self)  
+{
- return rb\_attr\_get(self, rb\_intern(“data”));  
+}
- 

+/\*

- 
  - call-seq:

- 
  - Socket::Option.int(level, optname, integer) =\> sockopt

- 
  - 

- 
  - Creates a new Socket::Option object which contains an int as data.

- 
  - 

- 
  - The size and endian is dependent on the host.

- 
  - 

- 
  - p Socket::Option.int(:SOCKET, :KEEPALIVE, 1)

- 
  - #=\> #\<Socket::Option: SOCKET KEEPALIVE 1\>

- \*/  
+static VALUE  
+sockopt\_s\_int(VALUE klass, VALUE vlevel, VALUE voptname, VALUE vint)  
+{
- int level = level\_arg(vlevel);
- int optname = optname\_arg(level, voptname);
- int i = NUM2INT(vint);
- return sockopt\_new(level, optname, rb\_str\_new((char\*)&i,  
sizeof(i)));  
+}
- 

+/\*

- 
  - call-seq:

- 
  - sockopt.int =\> integer

- 
  - 

- 
  - Returns the data in _sockopt_ as an int.

- 
  - 

- 
  - The size and endian is dependent on the host.

- 
  - 

- 
  - sockopt = Socket::Option.int(:SOCKET, :KEEPALIVE, 1)

- 
  - p sockopt.int =\> 1

- \*/  
+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);  
+}
- 

+static int  
+inspect\_int(int level, int optname, VALUE data, VALUE ret)  
+{

- if (RSTRING\_LEN(data) == sizeof(int)) {
- 

```
   int i;

```

- 

```
   memcpy((char*)&i, RSTRING_PTR(data), sizeof(int));

```

- 

```
   rb_str_catf(ret, " %d", i);

```

- 

```
   return 0;

```

- }
- else {
- 

```
   return -1;

```

- }  
+}
- 

+static int  
+inspect\_uint(int level, int optname, VALUE data, VALUE ret)  
+{

- if (RSTRING\_LEN(data) == sizeof(int)) {
- 

```
   unsigned int i;

```

- 

```
   memcpy((char*)&i, RSTRING_PTR(data), sizeof(unsigned int));

```

- 

```
   rb_str_catf(ret, " %u", i);

```

- 

```
   return 0;

```

- }
- else {
- 

```
   return -1;

```

- }  
+}
- 

+#if defined(SOL\_SOCKET) && defined(SO\_LINGER) /\* POSIX \*/  
+static int  
+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, " onoff:%d linger:%d", s.l_onoff, s.l_linger);

```

- 

```
   return 0;

```

- }
- else {
- 

```
   return -1;

```

- }  
+}  
+#endif
- 

+#if defined(SOL\_SOCKET) && defined(SO\_TYPE) /\* POSIX \*/  
+static int  
+inspect\_socktype(int level, int optname, VALUE data, VALUE ret)  
+{

- if (RSTRING\_LEN(data) == sizeof(int)) {
- 

```
   int i;

```

- 

```
   ID id;

```

- 

```
   memcpy((char*)&i, RSTRING_PTR(data), sizeof(int));

```

- 

```
   id = intern_socktype(i);

```

- 

```
   if (id)

```

- 

```
       rb_str_catf(ret, " %s", rb_id2name(id));

```

- 

```
   else

```

- 

```
       rb_str_catf(ret, " %d", i);

```

- 

```
   return 0;

```

- }
- else {
- 

```
   return -1;

```

- }  
+}  
+#endif
- 

+static int  
+inspect\_timeval(int level, int optname, VALUE data, VALUE ret)  
+{

- if (RSTRING\_LEN(data) == sizeof(struct linger)) {
- 

```
   struct timeval s;

```

- 

```
   memcpy((char*)&s, RSTRING_PTR(data), sizeof(s));

```

- 

```
   rb_str_catf(ret, " %ld.%06ldsec", (long)s.tv_sec, 

```

(long)s.tv\_usec);

- 

```
   return 0;

```

- }
- else {
- 

```
   return -1;

```

- }  
+}
- 

+static VALUE  
+sockopt\_inspect(VALUE self)  
+{

- int level = NUM2INT(sockopt\_level(self));
- int optname = NUM2INT(sockopt\_optname(self));
- VALUE data = sockopt\_data(self);
- VALUE v, ret;
- ID level\_id;
- 
- StringValue(data);
- 
- ret = rb\_sprintf("#\<%s: ", rb\_obj\_classname(self));
- 
- level\_id = intern\_level(level);
- if (level\_id)
- 

```
   rb_str_cat2(ret, 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);

```

- 
- switch (level) {  
+# if defined(SOL\_SOCKET)
- 

```
 case SOL_SOCKET:

```

- 

```
   switch (optname) {

```

+# if defined(SO\_DEBUG) /\* POSIX \*/

- 

```
     case SO_DEBUG: if (inspect_int(level, optname, data, ret) == 

```

-1) goto dump; break;  
+# endif  
+# if defined(SO\_ERROR) /\* POSIX \*/

- 

```
     case SO_ERROR: if (inspect_int(level, optname, data, ret) == 

```

-1) goto dump; break;  
+# endif  
+# if defined(SO\_TYPE) /\* POSIX \*/

- 

```
     case SO_TYPE: if (inspect_socktype(level, optname, data, ret) 

```

== -1) goto dump; break;  
+# endif  
+# if defined(SO\_ACCEPTCONN) /\* POSIX \*/

- 

```
     case SO_ACCEPTCONN: if (inspect_int(level, optname, data, 

```

ret) == -1) goto dump; break;  
+# endif  
+# if defined(SO\_BROADCAST) /\* POSIX \*/

- 

```
     case SO_BROADCAST: if (inspect_int(level, optname, data, ret) 

```

== -1) goto dump; break;  
+# endif  
+# if defined(SO\_REUSEADDR) /\* POSIX \*/

- 

```
     case SO_REUSEADDR: if (inspect_int(level, optname, data, ret) 

```

== -1) goto dump; break;  
+# endif  
+# if defined(SO\_KEEPALIVE) /\* POSIX \*/

- 

```
     case SO_KEEPALIVE: if (inspect_int(level, optname, data, ret) 

```

== -1) goto dump; break;  
+# endif  
+# if defined(SO\_OOBINLINE) /\* POSIX \*/

- 

```
     case SO_OOBINLINE: if (inspect_int(level, optname, data, ret) 

```

== -1) goto dump; break;  
+# endif  
+# if defined(SO\_SNDBUF) /\* POSIX \*/

- 

```
     case SO_SNDBUF: if (inspect_int(level, optname, data, ret) == 

```

-1) goto dump; break;  
+# endif  
+# if defined(SO\_RCVBUF) /\* POSIX \*/

- 

```
     case SO_RCVBUF: if (inspect_int(level, optname, data, ret) == 

```

-1) goto dump; break;  
+# endif  
+# if defined(SO\_DONTROUTE) /\* POSIX \*/

- 

```
     case SO_DONTROUTE: if (inspect_int(level, optname, data, ret) 

```

== -1) goto dump; break;  
+# endif  
+# if defined(SO\_RCVLOWAT) /\* POSIX \*/

- 

```
     case SO_RCVLOWAT: if (inspect_int(level, optname, data, ret) 

```

== -1) goto dump; break;  
+# endif  
+# if defined(SO\_SNDLOWAT) /\* POSIX \*/

- 

```
     case SO_SNDLOWAT: if (inspect_int(level, optname, data, ret) 

```

== -1) goto dump; break;  
+# endif  
+  
+# if defined(SO\_LINGER) /\* POSIX \*/

- 

```
     case SO_LINGER: if (inspect_linger(level, optname, data, ret) 

```

== -1) goto dump; break;  
+# endif  
+# if defined(SO\_RCVTIMEO) /\* POSIX \*/

- 

```
     case SO_RCVTIMEO: if (inspect_timeval(level, optname, data, 

```

ret) == -1) goto dump; break;  
+# endif  
+# if defined(SO\_SNDTIMEO) /\* POSIX \*/

- 

```
     case SO_SNDTIMEO: if (inspect_timeval(level, optname, data, 

```

ret) == -1) goto dump; break;  
+# endif  
+

- 

```
     default: goto dump;

```

- 

```
   }

```

- 

```
   break;

```

+# endif  
+  
+# if defined(IPPROTO\_IPV6)

- 

```
 case IPPROTO_IPV6:

```

- 

```
   switch (optname) {

```

- 

```
     /* IPV6_JOIN_GROUP ipv6_mreq, IPV6_LEAVE_GROUP ipv6_mreq */

```

+# if defined(IPV6\_MULTICAST\_HOPS) /\* POSIX \*/

- 

```
     case IPV6_MULTICAST_HOPS: if (inspect_int(level, optname, 

```

data, ret) == -1) goto dump; break;  
+# endif  
+# if defined(IPV6\_MULTICAST\_IF) /\* POSIX \*/

- 

```
     case IPV6_MULTICAST_IF: if (inspect_uint(level, optname, 

```

data, ret) == -1) goto dump; break;  
+# endif  
+# if defined(IPV6\_MULTICAST\_LOOP) /\* POSIX \*/

- 

```
     case IPV6_MULTICAST_LOOP: if (inspect_uint(level, optname, 

```

data, ret) == -1) goto dump; break;  
+# endif  
+# if defined(IPV6\_UNICAST\_HOPS) /\* POSIX \*/

- 

```
     case IPV6_UNICAST_HOPS: if (inspect_int(level, optname, data, 

```

ret) == -1) goto dump; break;  
+# endif  
+# if defined(IPV6\_V6ONLY) /\* POSIX \*/

- 

```
     case IPV6_V6ONLY: if (inspect_int(level, optname, data, ret) 

```

== -1) goto dump; break;  
+# endif

- 

```
     default: goto dump;

```

- 

```
   }

```

- 

```
   break;

```

+# endif  
+  
+# if defined(IPPROTO\_TCP)

- 

```
 case IPPROTO_TCP:

```

- 

```
   switch (optname) {

```

+# if defined(TCP\_NODELAY) /\* POSIX \*/

- 

```
     case TCP_NODELAY: if (inspect_int(level, optname, data, ret) 

```

== -1) goto dump; break;  
+# endif

- 

```
     default: goto dump;

```

- 

```
   }

```

- 

```
   break;

```

+# endif  
+

- 

```
 default:

```

- 

```
 dump:

```

- 

```
   data = rb_str_dump(data);

```

- 

```
   rb_str_catf(ret, " %s", StringValueCStr(data));

```

- }
- 
- rb\_str\_cat2(ret, “\>”);
- 
- return ret;  
+}
- 

+static VALUE  
+sockopt\_unpack(VALUE self, VALUE template)  
+{

- return rb\_funcall(sockopt\_data(self), rb\_intern(“unpack”), 1,  
template);  
+}
- 

+void  
+Init\_sockopt(void)  
+{

- rb\_cSockOpt = rb\_define\_class\_under(rb\_cSocket, “Option”,  
rb\_cObject);
- rb\_define\_method(rb\_cSockOpt, “initialize”, sockopt\_initialize, 3);
- rb\_define\_method(rb\_cSockOpt, “level”, sockopt\_level, 0);
- rb\_define\_method(rb\_cSockOpt, “optname”, sockopt\_optname, 0);
- rb\_define\_method(rb\_cSockOpt, “data”, sockopt\_data, 0);
- rb\_define\_method(rb\_cSockOpt, “inspect”, sockopt\_inspect, 0);
- 
- rb\_define\_singleton\_method(rb\_cSockOpt, “int”, sockopt\_s\_int, 3);
- rb\_define\_method(rb\_cSockOpt, “int”, sockopt\_int, 0);
- 
- rb\_define\_method(rb\_cSockOpt, “unpack”, sockopt\_unpack, 1);  
+}
- 

# Index: ext/socket/depend

— ext/socket/depend (revision 21646)  
+++ ext/socket/depend (working copy)  
@@ -13,6 +13,7 @@ sockssocket.o: sockssocket.c $(SOCK\_HEAD  
udpsocket.o: udpsocket.c $(SOCK\_HEADERS)  
unixsocket.o: unixsocket.c $(SOCK\_HEADERS)  
unixserver.o: unixserver.c $(SOCK\_HEADERS)  
+option.o: option.c $(SOCK\_HEADERS)  
raddrinfo.o: raddrinfo.c $(SOCK\_HEADERS)

# getnameinfo.o: getnameinfo.c $(arch\_hdrdir)/ruby/config.h addrinfo.h sockport.h Index: ext/socket/mkconstants.rb

— ext/socket/mkconstants.rb (revision 21646)  
+++ ext/socket/mkconstants.rb (working copy)  
@@ -254,6 +254,13 @@ def\_intern(‘intern\_family’, /\AAF\_/)  
def\_intern(‘intern\_protocol\_family’, /\APF\_/)  
def\_intern(‘intern\_socktype’, /\ASOCK\_/)  
def\_intern(‘intern\_ipproto’, /\AIPPROTO\_/)  
+def\_intern(‘intern\_level’, /\A(SOL\_SOCKET\z|IPPROTO\_)/,  
/\A(SOL\_|IPPROTO\_)/)  
+def\_intern(‘intern\_so\_optname’, /\ASO\_/, “SO\_”)  
+def\_intern(‘intern\_ip\_optname’, /\AIP\_/, “IP\_”)  
+def\_intern(‘intern\_ipv6\_optname’, /\AIPV6\_/, “IPV6\_”)  
+def\_intern(‘intern\_tcp\_optname’, /\ATCP\_/, “TCP\_”)  
+def\_intern(‘intern\_udp\_optname’, /\AUDP\_/, “UDP\_”)  
+def\_intern(‘intern\_scm\_optname’, /\ASCM\_/, “SCM\_”)

result \<\< ERB.new(\<\<‘EOS’, nil, ‘%’).result(binding)

# Index: ext/socket/extconf.rb

— ext/socket/extconf.rb (revision 21646)  
+++ ext/socket/extconf.rb (working copy)  
@@ -254,6 +254,7 @@ $objs = [  
“udpsocket.#{$OBJEXT}”,  
“unixsocket.#{$OBJEXT}”,  
“unixserver.#{$OBJEXT}”,

- “option.#{$OBJEXT}”,  
“raddrinfo.#{$OBJEXT}”  
]

# Index: ext/socket/basicsocket.c

— ext/socket/basicsocket.c (revision 21646)  
+++ ext/socket/basicsocket.c (working copy)  
@@ -192,14 +192,24 @@ bsock\_close\_write(VALUE sock)  
\*  
\*/  
static VALUE  
-bsock\_setsockopt(VALUE sock, VALUE lev, VALUE optname, VALUE val)  
+bsock\_setsockopt(int argc, VALUE \*argv, VALUE sock)  
{

- VALUE lev, optname, val;  
int level, option;  
rb\_io\_t \*fptr;  
int i;  
char \*v;  
int vlen;

- if (argc == 1) {

- 

```
   lev = rb_funcall(argv[0], rb_intern("level"), 0);

```

- 

```
   optname = rb_funcall(argv[0], rb_intern("optname"), 0);

```

- 

```
   val = rb_funcall(argv[0], rb_intern("data"), 0);

```

- }

- else {

- 

```
   rb_scan_args(argc, argv, "30", &lev, &optname, &val);

```

- }

- rb\_secure(2);  
level = level\_arg(lev);  
option = optname\_arg(level, optname);  
@@ -290,7 +300,7 @@ bsock\_getsockopt(VALUE sock, VALUE lev,  
if (getsockopt(fptr-\>fd, level, option, buf, &len) \< 0)  
rb\_sys\_fail\_path(fptr-\>pathv);

- return rb\_str\_new(buf, len);

- return sockopt\_new(level, option, rb\_str\_new(buf, len));  
#else  
rb\_notimplement();  
#endif  
@@ -626,7 +636,7 @@ Init\_basicsocket(void)  
rb\_define\_method(rb\_cBasicSocket, “close\_read”, bsock\_close\_read,  
0);  
rb\_define\_method(rb\_cBasicSocket, “close\_write”, bsock\_close\_write,  
0);  
rb\_define\_method(rb\_cBasicSocket, “shutdown”, bsock\_shutdown, -1);

- rb\_define\_method(rb\_cBasicSocket, “setsockopt”, bsock\_setsockopt,  
3);

- rb\_define\_method(rb\_cBasicSocket, “setsockopt”, bsock\_setsockopt,  
-1);  
rb\_define\_method(rb\_cBasicSocket, “getsockopt”, bsock\_getsockopt,  
2);  
rb\_define\_method(rb\_cBasicSocket, “getsockname”, bsock\_getsockname,  
0);  
rb\_define\_method(rb\_cBasicSocket, “getpeername”, bsock\_getpeername,  
0);  
Index: test/socket/test\_basicsocket.rb  
===================================================================  
— test/socket/test\_basicsocket.rb (revision 21646)  
+++ test/socket/test\_basicsocket.rb (working copy)  
@@ -15,19 +15,19 @@ class TestBasicSocket \< Test::Unit::Test  
def test\_getsockopt  
inet\_stream do |s|  
n = s.getsockopt(Socket::SOL\_SOCKET, Socket::SO\_TYPE)

- 

```
 assert_equal([Socket::SOCK_STREAM].pack("i"), n)

```

- 

```
 assert_equal([Socket::SOCK_STREAM].pack("i"), n.data)

 n = s.getsockopt("SOL_SOCKET", "SO_TYPE")

```

- 

```
 assert_equal([Socket::SOCK_STREAM].pack("i"), n)

```

- 

```
 assert_equal([Socket::SOCK_STREAM].pack("i"), n.data)

 n = s.getsockopt(:SOL_SOCKET, :SO_TYPE)

```

- 

```
 assert_equal([Socket::SOCK_STREAM].pack("i"), n)

```

- 

```
 assert_equal([Socket::SOCK_STREAM].pack("i"), n.data)

 n = s.getsockopt(:SOCKET, :TYPE)

```

- 

```
 assert_equal([Socket::SOCK_STREAM].pack("i"), n)

```

- 

```
 assert_equal([Socket::SOCK_STREAM].pack("i"), n.data)

 n = s.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR)

```

- 

```
 assert_equal([0].pack("i"), n)

```

- 

```
 assert_equal([0].pack("i"), n.data)

 val = Object.new
 class << val; self end.send(:define_method, :to_int) {
```
