diff options
Diffstat (limited to 'ext/socket/option.c')
| -rw-r--r-- | ext/socket/option.c | 152 |
1 files changed, 78 insertions, 74 deletions
diff --git a/ext/socket/option.c b/ext/socket/option.c index db7ab8252d..0d818d0c70 100644 --- a/ext/socket/option.c +++ b/ext/socket/option.c @@ -27,6 +27,12 @@ VALUE rb_cSockOpt; # define USE_INSPECT_BYTE 1 #endif +#define check_size(len, size) \ + ((len) == (size) ? \ + (void)0 : \ + rb_raise(rb_eTypeError, "size differ. expected as "#size"=%d but %ld", \ + (int)size, (long)(len))) + static VALUE sockopt_pack_byte(VALUE value) { @@ -100,9 +106,9 @@ sockopt_initialize(VALUE self, VALUE vfamily, VALUE vlevel, VALUE voptname, VALU VALUE rsock_sockopt_new(int family, int level, int optname, VALUE data) { - NEWOBJ_OF(obj, struct RObject, rb_cSockOpt, T_OBJECT); + VALUE obj = rb_obj_alloc(rb_cSockOpt); StringValue(data); - sockopt_initialize((VALUE)obj, INT2NUM(family), INT2NUM(level), INT2NUM(optname), data); + sockopt_initialize(obj, INT2NUM(family), INT2NUM(level), INT2NUM(optname), data); return (VALUE)obj; } @@ -211,12 +217,9 @@ sockopt_s_byte(VALUE klass, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE v 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)); + check_size(RSTRING_LEN(data), sizeof(char)); return CHR2FIX(*RSTRING_PTR(data)); } @@ -257,9 +260,7 @@ 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)); + check_size(RSTRING_LEN(data), sizeof(int)); memcpy((char*)&i, RSTRING_PTR(data), sizeof(int)); return INT2NUM(i); } @@ -271,6 +272,8 @@ sockopt_int(VALUE self) * Creates a new Socket::Option object which contains boolean as data. * Actually 0 or 1 as int is used. * + * require 'socket' + * * p Socket::Option.bool(:INET, :SOCKET, :KEEPALIVE, true) * #=> #<Socket::Option: INET SOCKET KEEPALIVE 1> * @@ -301,12 +304,15 @@ static VALUE sockopt_bool(VALUE self) { int i; + long len; 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)); + len = RSTRING_LEN(data); + if (len == 1) { + return *RSTRING_PTR(data) == 0 ? Qfalse : Qtrue; + } + check_size(len, sizeof(int)); + memcpy((char*)&i, RSTRING_PTR(data), len); return i == 0 ? Qfalse : Qtrue; } @@ -358,9 +364,7 @@ sockopt_linger(VALUE self) 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)); + check_size(RSTRING_LEN(data), sizeof(struct linger)); memcpy((char*)&l, RSTRING_PTR(data), sizeof(struct linger)); switch (l.l_onoff) { case 0: vonoff = Qfalse; break; @@ -402,7 +406,7 @@ sockopt_s_ipv4_multicast_loop(VALUE klass, VALUE value) * call-seq: * sockopt.ipv4_multicast_loop => integer * - * Returns the ipv4_multicast_loop data in _sockopt_ as a integer. + * Returns the ipv4_multicast_loop data in _sockopt_ as an integer. * * sockopt = Socket::Option.ipv4_multicast_loop(10) * p sockopt.ipv4_multicast_loop => 10 @@ -416,11 +420,11 @@ sockopt_ipv4_multicast_loop(VALUE self) #if defined(IPPROTO_IP) && defined(IP_MULTICAST_LOOP) if (family == AF_INET && level == IPPROTO_IP && optname == IP_MULTICAST_LOOP) { - return XCAT(sockopt_,TYPE_IP_MULTICAST_LOOP)(self); + return XCAT(sockopt_,TYPE_IP_MULTICAST_LOOP)(self); } #endif rb_raise(rb_eTypeError, "ipv4_multicast_loop socket option expected"); - UNREACHABLE; + UNREACHABLE_RETURN(Qnil); } #define inspect_ipv4_multicast_loop(a,b,c,d) \ @@ -453,7 +457,7 @@ sockopt_s_ipv4_multicast_ttl(VALUE klass, VALUE value) * call-seq: * sockopt.ipv4_multicast_ttl => integer * - * Returns the ipv4_multicast_ttl data in _sockopt_ as a integer. + * Returns the ipv4_multicast_ttl data in _sockopt_ as an integer. * * sockopt = Socket::Option.ipv4_multicast_ttl(10) * p sockopt.ipv4_multicast_ttl => 10 @@ -467,11 +471,11 @@ sockopt_ipv4_multicast_ttl(VALUE self) #if defined(IPPROTO_IP) && defined(IP_MULTICAST_TTL) if (family == AF_INET && level == IPPROTO_IP && optname == IP_MULTICAST_TTL) { - return XCAT(sockopt_,TYPE_IP_MULTICAST_TTL)(self); + return XCAT(sockopt_,TYPE_IP_MULTICAST_TTL)(self); } #endif rb_raise(rb_eTypeError, "ipv4_multicast_ttl socket option expected"); - UNREACHABLE; + UNREACHABLE_RETURN(Qnil); } #define inspect_ipv4_multicast_ttl(a,b,c,d) \ @@ -643,7 +647,7 @@ inspect_timeval_as_interval(int level, int optname, VALUE data, VALUE ret) */ #if !defined HAVE_INET_NTOP && ! defined _WIN32 -static const char * +const char * inet_ntop(int af, const void *addr, char *numaddr, size_t numaddr_len) { #ifdef HAVE_INET_NTOA @@ -653,15 +657,11 @@ inet_ntop(int af, const void *addr, char *numaddr, size_t numaddr_len) #else unsigned long x = ntohl(*(unsigned long*)addr); snprintf(numaddr, numaddr_len, "%d.%d.%d.%d", - (int) (x>>24) & 0xff, (int) (x>>16) & 0xff, - (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff); + (int) (x>>24) & 0xff, (int) (x>>16) & 0xff, + (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff); #endif return numaddr; } -#elif defined __MINGW32__ -# define inet_ntop(f,a,n,l) rb_w32_inet_ntop(f,a,n,l) -#elif defined _MSC_VER && RUBY_MSVCRT_VERSION < 90 -const char *WSAAPI inet_ntop(int, const void *, char *, size_t); #endif /* Although the buffer size needed depends on the prefixes, "%u" may generate "4294967295". */ @@ -670,10 +670,10 @@ rb_if_indextoname(const char *succ_prefix, const char *fail_prefix, unsigned int { #if defined(HAVE_IF_INDEXTONAME) char ifbuf[IFNAMSIZ]; - if (if_indextoname(ifindex, ifbuf) == NULL) - return snprintf(buf, len, "%s%u", fail_prefix, ifindex); - else + if (if_indextoname(ifindex, ifbuf)) return snprintf(buf, len, "%s%s", succ_prefix, ifbuf); + else + return snprintf(buf, len, "%s%u", fail_prefix, ifindex); #else # ifndef IFNAMSIZ # define IFNAMSIZ (sizeof(unsigned int)*3+1) @@ -928,7 +928,12 @@ inspect_tcpi_usec(VALUE ret, const char *prefix, uint32_t t) rb_str_catf(ret, "%s%u.%06us", prefix, t / 1000000, t % 1000000); } -#if defined(__linux__) || defined(__sun) +#if !defined __FreeBSD__ && ( \ + defined HAVE_STRUCT_TCP_INFO_TCPI_LAST_DATA_SENT || \ + defined HAVE_STRUCT_TCP_INFO_TCPI_LAST_DATA_RECV || \ + defined HAVE_STRUCT_TCP_INFO_TCPI_LAST_ACK_SENT || \ + defined HAVE_STRUCT_TCP_INFO_TCPI_LAST_ACK_RECV || \ + 0) static void inspect_tcpi_msec(VALUE ret, const char *prefix, uint32_t t) { @@ -1054,16 +1059,16 @@ inspect_tcp_info(int level, int optname, VALUE data, VALUE ret) rb_str_catf(ret, " fackets=%u", s.tcpi_fackets); #endif #ifdef HAVE_STRUCT_TCP_INFO_TCPI_LAST_DATA_SENT - inspect_tcpi_last_data_sent(ret, s.tcpi_last_data_sent); + inspect_tcpi_last_data_sent(ret, s.tcpi_last_data_sent); #endif #ifdef HAVE_STRUCT_TCP_INFO_TCPI_LAST_ACK_SENT - inspect_tcpi_last_ack_sent(ret, s.tcpi_last_ack_sent); + inspect_tcpi_last_ack_sent(ret, s.tcpi_last_ack_sent); #endif #ifdef HAVE_STRUCT_TCP_INFO_TCPI_LAST_DATA_RECV - inspect_tcpi_last_data_recv(ret, s.tcpi_last_data_recv); + inspect_tcpi_last_data_recv(ret, s.tcpi_last_data_recv); #endif #ifdef HAVE_STRUCT_TCP_INFO_TCPI_LAST_ACK_RECV - inspect_tcpi_last_ack_recv(ret, s.tcpi_last_ack_recv); + inspect_tcpi_last_ack_recv(ret, s.tcpi_last_ack_recv); #endif #ifdef HAVE_STRUCT_TCP_INFO_TCPI_PMTU rb_str_catf(ret, " pmtu=%u", s.tcpi_pmtu); @@ -1072,10 +1077,10 @@ inspect_tcp_info(int level, int optname, VALUE data, VALUE ret) rb_str_catf(ret, " rcv_ssthresh=%u", s.tcpi_rcv_ssthresh); #endif #ifdef HAVE_STRUCT_TCP_INFO_TCPI_RTT - inspect_tcpi_rtt(ret, s.tcpi_rtt); + inspect_tcpi_rtt(ret, s.tcpi_rtt); #endif #ifdef HAVE_STRUCT_TCP_INFO_TCPI_RTTVAR - inspect_tcpi_rttvar(ret, s.tcpi_rttvar); + inspect_tcpi_rttvar(ret, s.tcpi_rttvar); #endif #ifdef HAVE_STRUCT_TCP_INFO_TCPI_SND_SSTHRESH rb_str_catf(ret, " snd_ssthresh=%u", s.tcpi_snd_ssthresh); @@ -1145,7 +1150,7 @@ inspect_peercred(int level, int optname, VALUE data, VALUE ret) RUBY_SOCK_PEERCRED cred; memcpy(&cred, RSTRING_PTR(data), sizeof(RUBY_SOCK_PEERCRED)); rb_str_catf(ret, " pid=%u euid=%u egid=%u", - (unsigned)cred.pid, (unsigned)cred.uid, (unsigned)cred.gid); + (unsigned)cred.pid, (unsigned)cred.uid, (unsigned)cred.gid); rb_str_cat2(ret, " (ucred)"); return 1; } @@ -1166,14 +1171,14 @@ inspect_local_peercred(int level, int optname, VALUE data, VALUE ret) return 0; rb_str_catf(ret, " version=%u", cred.cr_version); rb_str_catf(ret, " euid=%u", cred.cr_uid); - if (cred.cr_ngroups) { - int i; - const char *sep = " groups="; - for (i = 0; i < cred.cr_ngroups; i++) { - rb_str_catf(ret, "%s%u", sep, cred.cr_groups[i]); - sep = ","; - } - } + if (cred.cr_ngroups) { + int i; + const char *sep = " groups="; + for (i = 0; i < cred.cr_ngroups; i++) { + rb_str_catf(ret, "%s%u", sep, cred.cr_groups[i]); + sep = ","; + } + } rb_str_cat2(ret, " (xucred)"); return 1; } @@ -1211,42 +1216,42 @@ sockopt_inspect(VALUE self) family_id = rsock_intern_family_noprefix(family); if (family_id) - rb_str_catf(ret, " %s", rb_id2name(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); + 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 +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN else if (family == AF_UNIX) { - rb_str_catf(ret, " level:%d", level); + 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); + 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, " %"PRIsVALUE, rb_sym2str(v)); - else - rb_str_catf(ret, " optname:%d", optname); + 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, " %"PRIsVALUE, rb_sym2str(v)); + else + rb_str_catf(ret, " optname:%d", optname); } else { rb_str_catf(ret, " level:%d", level); @@ -1388,7 +1393,7 @@ sockopt_inspect(VALUE self) } break; -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN case AF_UNIX: switch (level) { case 0: @@ -1470,4 +1475,3 @@ rsock_init_sockopt(void) rb_define_method(rb_cSockOpt, "to_s", sockopt_data, 0); /* compatibility for ruby before 1.9.2 */ } - |
