raindrops RubyGem user+dev discussion/patches/pulls/bugs/help
 help / color / mirror / Atom feed
From: Eric Wong <e@80x24.org>
To: raindrops-public@bogomips.org
Subject: [PATCH 2/2] define Raindrops::TCP hash for TCP states
Date: Thu, 16 Mar 2017 03:16:52 +0000
Message-ID: <20170316031652.17433-3-e@80x24.org> (raw)
In-Reply-To: <20170316031652.17433-1-e@80x24.org>

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 @@
 	     "#{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 @@ def test_tcp_server_state_closed
     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)
-- 
EW


  parent reply	other threads:[~2017-03-16  3:16 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-16  3:16 [PATCH 0/2] support TCP_INFO under FreeBSD Eric Wong
2017-03-16  3:16 ` [PATCH 1/2] tcp_info: support this struct " Eric Wong
2017-03-16  3:16 ` Eric Wong [this message]
2017-03-21  2:55 ` [PATCH (ccc)] http_request: support proposed Raindrops::TCP states on Eric Wong
2017-03-21  7:50   ` Simon Eskildsen
2017-03-21  8:19     ` Eric Wong
2017-03-21 18:48   ` Jeremy Evans
2017-03-21 19:12     ` Eric Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://yhbt.net/raindrops/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170316031652.17433-3-e@80x24.org \
    --to=e@80x24.org \
    --cc=raindrops-public@bogomips.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

raindrops RubyGem user+dev discussion/patches/pulls/bugs/help

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://yhbt.net/raindrops-public
	git clone --mirror http://ou63pmih66umazou.onion/raindrops-public

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V1 raindrops-public raindrops-public/ https://yhbt.net/raindrops-public \
		raindrops-public@yhbt.net raindrops-public@bogomips.org raindrops@librelist.org raindrops@librelist.com
	public-inbox-index raindrops-public

Example config snippet for mirrors.
Newsgroups are available over NNTP:
	nntp://news.public-inbox.org/inbox.comp.lang.ruby.raindrops
	nntp://ou63pmih66umazou.onion/inbox.comp.lang.ruby.raindrops
 note: .onion URLs require Tor: https://www.torproject.org/

code repositories for the project(s) associated with this inbox:

	raindrops.git

AGPL code for this site: git clone https://public-inbox.org/public-inbox.git