#ifdef __linux__ #include #include #include #include #ifdef TCP_INFO #include "my_fileno.h" #define TCPI_ATTR_READER(x) \ static VALUE tcp_info_##x(VALUE self) \ { \ struct tcp_info *info = DATA_PTR(self); \ return UINT2NUM((uint32_t)info->tcpi_##x); \ } TCPI_ATTR_READER(state) TCPI_ATTR_READER(ca_state) TCPI_ATTR_READER(retransmits) TCPI_ATTR_READER(probes) TCPI_ATTR_READER(backoff) TCPI_ATTR_READER(options) TCPI_ATTR_READER(snd_wscale) TCPI_ATTR_READER(rcv_wscale) TCPI_ATTR_READER(rto) TCPI_ATTR_READER(ato) TCPI_ATTR_READER(snd_mss) TCPI_ATTR_READER(rcv_mss) TCPI_ATTR_READER(unacked) TCPI_ATTR_READER(sacked) TCPI_ATTR_READER(lost) TCPI_ATTR_READER(retrans) TCPI_ATTR_READER(fackets) TCPI_ATTR_READER(last_data_sent) TCPI_ATTR_READER(last_ack_sent) TCPI_ATTR_READER(last_data_recv) TCPI_ATTR_READER(last_ack_recv) TCPI_ATTR_READER(pmtu) TCPI_ATTR_READER(rcv_ssthresh) TCPI_ATTR_READER(rtt) TCPI_ATTR_READER(rttvar) TCPI_ATTR_READER(snd_ssthresh) TCPI_ATTR_READER(snd_cwnd) TCPI_ATTR_READER(advmss) TCPI_ATTR_READER(reordering) TCPI_ATTR_READER(rcv_rtt) TCPI_ATTR_READER(rcv_space) TCPI_ATTR_READER(total_retrans) static VALUE alloc(VALUE klass) { struct tcp_info *info = xmalloc(sizeof(struct tcp_info)); /* Data_Make_Struct has an extra memset 0 which is so wasteful */ return Data_Wrap_Struct(klass, NULL, -1, info); } /* * call-seq: * * Raindrops::TCP_Info.new(tcp_socket) -> TCP_Info object * * Reads a TCP_Info object from any given +tcp_socket+. See the tcp(7) * manpage and /usr/include/linux/tcp.h for more details. */ static VALUE init(VALUE self, VALUE io) { int fd = my_fileno(io); struct tcp_info *info = DATA_PTR(self); socklen_t len = (socklen_t)sizeof(struct tcp_info); int rc = getsockopt(fd, IPPROTO_TCP, TCP_INFO, info, &len); if (rc != 0) rb_sys_fail("getsockopt"); return self; } void Init_raindrops_linux_tcp_info(void) { VALUE cRaindrops = rb_const_get(rb_cObject, rb_intern("Raindrops")); VALUE cTCP_Info; /* * Document-class: Raindrops::TCP_Info * * This is used to wrap "struct tcp_info" as described in tcp(7) * and /usr/include/linux/tcp.h. The following readers methods * are defined corresponding to the "tcpi_" fields in the * tcp_info struct. * * In particular, the +last_data_recv+ field is useful for measuring * the amount of time a client spent in the listen queue before * +accept()+, but only if +TCP_DEFER_ACCEPT+ is used with the * listen socket (it is on by default in Unicorn). * * - state * - ca_state * - retransmits * - probes * - backoff * - options * - snd_wscale * - rcv_wscale * - rto * - ato * - snd_mss * - rcv_mss * - unacked * - sacked * - lost * - retrans * - fackets * - last_data_sent * - last_ack_sent * - last_data_recv * - last_ack_recv * - pmtu * - rcv_ssthresh * - rtt * - rttvar * - snd_ssthresh * - snd_cwnd * - advmss * - reordering * - rcv_rtt * - rcv_space * - total_retrans * * http://kernel.org/doc/man-pages/online/pages/man7/tcp.7.html */ cTCP_Info = rb_define_class_under(cRaindrops, "TCP_Info", rb_cObject); rb_define_alloc_func(cTCP_Info, alloc); rb_define_private_method(cTCP_Info, "initialize", init, 1); rb_define_method(cTCP_Info, "get!", init, 1); #define TCPI_DEFINE_METHOD(x) \ rb_define_method(cTCP_Info, #x, tcp_info_##x, 0) TCPI_DEFINE_METHOD(state); TCPI_DEFINE_METHOD(ca_state); TCPI_DEFINE_METHOD(retransmits); TCPI_DEFINE_METHOD(probes); TCPI_DEFINE_METHOD(backoff); TCPI_DEFINE_METHOD(options); TCPI_DEFINE_METHOD(snd_wscale); TCPI_DEFINE_METHOD(rcv_wscale); TCPI_DEFINE_METHOD(rto); TCPI_DEFINE_METHOD(ato); TCPI_DEFINE_METHOD(snd_mss); TCPI_DEFINE_METHOD(rcv_mss); TCPI_DEFINE_METHOD(unacked); TCPI_DEFINE_METHOD(sacked); TCPI_DEFINE_METHOD(lost); TCPI_DEFINE_METHOD(retrans); TCPI_DEFINE_METHOD(fackets); TCPI_DEFINE_METHOD(last_data_sent); TCPI_DEFINE_METHOD(last_ack_sent); TCPI_DEFINE_METHOD(last_data_recv); TCPI_DEFINE_METHOD(last_ack_recv); TCPI_DEFINE_METHOD(pmtu); TCPI_DEFINE_METHOD(rcv_ssthresh); TCPI_DEFINE_METHOD(rtt); TCPI_DEFINE_METHOD(rttvar); TCPI_DEFINE_METHOD(snd_ssthresh); TCPI_DEFINE_METHOD(snd_cwnd); TCPI_DEFINE_METHOD(advmss); TCPI_DEFINE_METHOD(reordering); TCPI_DEFINE_METHOD(rcv_rtt); TCPI_DEFINE_METHOD(rcv_space); TCPI_DEFINE_METHOD(total_retrans); } #endif /* TCP_INFO */ #endif /* __linux__ */