commit bf2fb0a16091201a9b2798ebdea54e03c1c3e61b (patch)
parent 17d5723 tcp_info: support this struct under FreeBSD
tree a3cd9a2713024e87633908d59d545a07827f3b9a
author Eric Wong <e@80x24.org> 2017-03-16 03:16:52 +0000
committer Eric Wong <e@80x24.org> 2017-03-17 22:39:12 +0000
define Raindrops::TCP hash for TCP states
FreeBSD not only uses different values than Linux for TCP
states, but different names, too. To ease writing portable code
between the OSes, do more CPP metaprogramming via extconf.rb
and define a common hash supported on both OSes.
Putting all this in a hash allows for easy dumping and mapping
in an OS-neutral way, since the actual TCP states are
OS-independent.
---
ext/raindrops/extconf.rb | 27 +++++++++++++++++++++++++++
ext/raindrops/tcp_info.c | 21 +++++++++++++++++++++
test/test_tcp_info.rb | 3 +++
3 files changed, 51 insertions(+)
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)
glossary
--------
Commit objects reference one tree, and zero or more parents.
Single parent commits can typically generate a patch in
unified diff format via `git format-patch'.
Multiple parents means the commit is a merge.
Root commits have no ancestor. Note that it is
possible to have multiple root commits when merging independent histories.
Every commit references one top-level tree object.
git clone http://yhbt.net/raindrops.git