diff options
author | Eric Wong <normalperson@yhbt.net> | 2011-02-22 19:24:54 -0800 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2011-02-23 13:14:27 -0800 |
commit | db192979f096d0153ad14e530e1e2e193289c7e0 (patch) | |
tree | 356c4a8bf64f30dd6c4886adc92f253bd4bf831d /ext | |
parent | ebc2093847705c382b4d83ed5120e44b9afad3c0 (diff) | |
download | raindrops-db192979f096d0153ad14e530e1e2e193289c7e0.tar.gz |
This returns a Raindrops::TCP_Info object that wraps a tcp_info struct.
Diffstat (limited to 'ext')
-rw-r--r-- | ext/raindrops/linux_tcp_info.c | 114 | ||||
-rw-r--r-- | ext/raindrops/my_fileno.h | 36 | ||||
-rw-r--r-- | ext/raindrops/raindrops.c | 2 |
3 files changed, 152 insertions, 0 deletions
diff --git a/ext/raindrops/linux_tcp_info.c b/ext/raindrops/linux_tcp_info.c new file mode 100644 index 0000000..8ca3585 --- /dev/null +++ b/ext/raindrops/linux_tcp_info.c @@ -0,0 +1,114 @@ +#include <ruby.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#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); +} + +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; + + 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); + +#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 */ diff --git a/ext/raindrops/my_fileno.h b/ext/raindrops/my_fileno.h new file mode 100644 index 0000000..bdf1a5f --- /dev/null +++ b/ext/raindrops/my_fileno.h @@ -0,0 +1,36 @@ +#include <ruby.h> +#ifdef HAVE_RUBY_IO_H +# include <ruby/io.h> +#else +# include <stdio.h> +# include <rubyio.h> +#endif + +#if ! HAVE_RB_IO_T +# define rb_io_t OpenFile +#endif + +#ifdef GetReadFile +# define FPTR_TO_FD(fptr) (fileno(GetReadFile(fptr))) +#else +# if !HAVE_RB_IO_T || (RUBY_VERSION_MAJOR == 1 && RUBY_VERSION_MINOR == 8) +# define FPTR_TO_FD(fptr) fileno(fptr->f) +# else +# define FPTR_TO_FD(fptr) fptr->fd +# endif +#endif + +static int my_fileno(VALUE io) +{ + rb_io_t *fptr; + int fd; + + if (TYPE(io) != T_FILE) + io = rb_convert_type(io, T_FILE, "IO", "to_io"); + GetOpenFile(io, fptr); + fd = FPTR_TO_FD(fptr); + + if (fd < 0) + rb_raise(rb_eIOError, "closed stream"); + return fd; +} diff --git a/ext/raindrops/raindrops.c b/ext/raindrops/raindrops.c index e43dc2c..599f39d 100644 --- a/ext/raindrops/raindrops.c +++ b/ext/raindrops/raindrops.c @@ -172,6 +172,7 @@ static VALUE aref(VALUE self, VALUE index) #ifdef __linux__ void Init_raindrops_linux_inet_diag(void); +void Init_raindrops_linux_tcp_info(void); #endif #ifndef _SC_NPROCESSORS_ONLN @@ -215,5 +216,6 @@ void Init_raindrops_ext(void) #ifdef __linux__ Init_raindrops_linux_inet_diag(); + Init_raindrops_linux_tcp_info(); #endif } |