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);
}
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);
}
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) {
case SO_DEBUG: inspected = inspect_int(level, optname, data, ret); break;
case SO_ERROR: inspected = inspect_errno(level, optname, data, ret); break;
case SO_TYPE: inspected = inspect_socktype(level, optname, data, ret); break;
case SO_ACCEPTCONN: inspected = inspect_int(level, optname, data, ret); break;
case SO_BROADCAST: inspected = inspect_int(level, optname, data, ret); break;
case SO_REUSEADDR: inspected = inspect_int(level, optname, data, ret); break;
case SO_KEEPALIVE: inspected = inspect_int(level, optname, data, ret); break;
case SO_OOBINLINE: inspected = inspect_int(level, optname, data, ret); break;
case SO_SNDBUF: inspected = inspect_int(level, optname, data, ret); break;
case SO_RCVBUF: inspected = inspect_int(level, optname, data, ret); break;
case SO_DONTROUTE: inspected = inspect_int(level, optname, data, ret); break;
case SO_RCVLOWAT: inspected = inspect_int(level, optname, data, ret); break;
case SO_SNDLOWAT: inspected = inspect_int(level, optname, data, ret); break;
case SO_LINGER: inspected = inspect_linger(level, optname, data, ret); break;
case SO_RCVTIMEO: inspected = inspect_timeval_as_interval(level, optname, data, ret); break;
case SO_SNDTIMEO: inspected = inspect_timeval_as_interval(level, optname, data, ret); break;
case SO_PEERCRED: inspected = inspect_peercred(level, optname, data, ret); break;
}
break;
}
break;
case AF_INET:
case AF_INET6:
switch (level) {
case IPPROTO_IPV6:
switch (optname) {
/* IPV6_JOIN_GROUP ipv6_mreq, IPV6_LEAVE_GROUP ipv6_mreq */
case IPV6_MULTICAST_HOPS: inspected = inspect_int(level, optname, data, ret); break;
case IPV6_MULTICAST_IF: inspected = inspect_uint(level, optname, data, ret); break;
case IPV6_MULTICAST_LOOP: inspected = inspect_uint(level, optname, data, ret); break;
case IPV6_UNICAST_HOPS: inspected = inspect_int(level, optname, data, ret); break;
case IPV6_V6ONLY: inspected = inspect_int(level, optname, data, ret); break;
}
break;
case IPPROTO_TCP:
switch (optname) {
case TCP_NODELAY: inspected = inspect_int(level, optname, data, ret); break;
}
break;
}
break;
case AF_UNIX:
switch (level) {
case 0:
switch (optname) {
case LOCAL_PEERCRED: inspected = inspect_local_peercred(level, optname, data, ret); break;
}
break;
}
break;
}
if (!inspected) {
rb_str_cat2(ret, " ");
rb_str_append(ret, rb_str_dump(data));
}
rb_str_cat2(ret, ">");
return ret;
}