about summary refs log tree commit homepage
diff options
context:
space:
mode:
-rw-r--r--ext/raindrops/extconf.rb27
-rw-r--r--ext/raindrops/tcp_info.c21
-rw-r--r--test/test_tcp_info.rb3
3 files changed, 51 insertions, 0 deletions
diff --git a/ext/raindrops/extconf.rb b/ext/raindrops/extconf.rb
index 5273b74..86c7d78 100644
--- a/ext/raindrops/extconf.rb
+++ b/ext/raindrops/extconf.rb
@@ -82,6 +82,33 @@ EOF
              "#{Shellwords.shellescape(
                 %Q[rb_define_method(cTCP_Info,#{rbmethod},#{cfunc},0)])}"
   end
+  tcp_state_map = {
+    ESTABLISHED: %w(TCP_ESTABLISHED TCPS_ESTABLISHED),
+    SYN_SENT: %w(TCP_SYN_SENT TCPS_SYN_SENT),
+    SYN_RECV: %w(TCP_SYN_RECV TCPS_SYN_RECEIVED),
+    FIN_WAIT1: %w(TCP_FIN_WAIT1 TCPS_FIN_WAIT_1),
+    FIN_WAIT2: %w(TCP_FIN_WAIT2 TCPS_FIN_WAIT_2),
+    TIME_WAIT: %w(TCP_TIME_WAIT TCPS_TIME_WAIT),
+    CLOSE: %w(TCP_CLOSE TCPS_CLOSED),
+    CLOSE_WAIT: %w(TCP_CLOSE_WAIT TCPS_CLOSE_WAIT),
+    LAST_ACK: %w(TCP_LAST_ACK TCPS_LAST_ACK),
+    LISTEN: %w(TCP_LISTEN TCPS_LISTEN),
+    CLOSING: %w(TCP_CLOSING TCPS_CLOSING),
+  }
+  nstate = 0
+  tcp_state_map.each do |state, try|
+    try.each do |os_name|
+      have_const(os_name, headers) or next
+      tcp_state_map[state] = os_name
+      nstate += 1
+    end
+  end
+  if nstate == tcp_state_map.size
+    $defs << '-DRAINDROPS_TCP_STATES_ALL_KNOWN=1'
+    tcp_state_map.each do |state, name|
+      $defs << "-DRAINDROPS_TCP_#{state}=#{name}"
+    end
+  end
 end
 
 have_func("getpagesize", "unistd.h")
diff --git a/ext/raindrops/tcp_info.c b/ext/raindrops/tcp_info.c
index dc615f7..3e241a1 100644
--- a/ext/raindrops/tcp_info.c
+++ b/ext/raindrops/tcp_info.c
@@ -191,5 +191,26 @@ void Init_raindrops_tcp_info(void)
         DEFINE_METHOD_tcp_info_tcpi_rcv_rtt;
         DEFINE_METHOD_tcp_info_tcpi_rcv_space;
         DEFINE_METHOD_tcp_info_tcpi_total_retrans;
+
+#ifdef RAINDROPS_TCP_STATES_ALL_KNOWN
+        {
+#define TCPSET(n,v) rb_hash_aset(tcp, ID2SYM(rb_intern(#n)), INT2NUM(v))
+                VALUE tcp = rb_hash_new();
+                TCPSET(ESTABLISHED, RAINDROPS_TCP_ESTABLISHED);
+                TCPSET(SYN_SENT, RAINDROPS_TCP_SYN_SENT);
+                TCPSET(SYN_RECV, RAINDROPS_TCP_SYN_RECV);
+                TCPSET(FIN_WAIT1, RAINDROPS_TCP_FIN_WAIT1);
+                TCPSET(FIN_WAIT2, RAINDROPS_TCP_FIN_WAIT2);
+                TCPSET(TIME_WAIT, RAINDROPS_TCP_TIME_WAIT);
+                TCPSET(CLOSE, RAINDROPS_TCP_CLOSE);
+                TCPSET(CLOSE_WAIT, RAINDROPS_TCP_CLOSE_WAIT);
+                TCPSET(LAST_ACK, RAINDROPS_TCP_LAST_ACK);
+                TCPSET(LISTEN, RAINDROPS_TCP_LISTEN);
+                TCPSET(CLOSING, RAINDROPS_TCP_CLOSING);
+#undef TCPSET
+                OBJ_FREEZE(tcp);
+                rb_define_const(cRaindrops, "TCP", tcp);
+        }
+#endif
 }
 #endif /* HAVE_STRUCT_TCP_INFO */
diff --git a/test/test_tcp_info.rb b/test/test_tcp_info.rb
index 15df087..b107565 100644
--- a/test/test_tcp_info.rb
+++ b/test/test_tcp_info.rb
@@ -73,6 +73,9 @@ class TestTCP_Info < Test::Unit::TestCase
     a = s.accept
     i.get!(a)
     state = i.state
+    if Raindrops.const_defined?(:TCP)
+      assert_equal state, Raindrops::TCP[:ESTABLISHED]
+    end
     c = c.close
     sleep(0.01) # wait for kernel to update state
     i.get!(a)