diff options
author | Eric Wong <normalperson@yhbt.net> | 2012-12-27 01:16:56 +0000 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2012-12-27 01:23:34 +0000 |
commit | f61cef65b8a8816160c622324b4f1aad55034e4a (patch) | |
tree | d5c5b285acb51b12bf407e03f304ab602c283a3d /test | |
parent | 7a3fc55424338ad458cc719d4cb3c4e28802d5cb (diff) | |
download | kgio-f61cef65b8a8816160c622324b4f1aad55034e4a.tar.gz |
Server support just requires exposing one constant for setsockopt: Kgio::TCP_FASTOPEN Client support implements a new Kgio::Socket#fastopen method. This new method wraps the the sendto() syscall. With TCP Fast Open, the sendto() syscall is overloaded for stream sockets to implement the functionality of both connect() + write() Since it only makes sense to use _blocking_ I/O for sendto(), TFO clients are only supported in Ruby implementations with native threads.
Diffstat (limited to 'test')
-rw-r--r-- | test/test_tfo.rb | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/test/test_tfo.rb b/test/test_tfo.rb new file mode 100644 index 0000000..846e273 --- /dev/null +++ b/test/test_tfo.rb @@ -0,0 +1,70 @@ +require 'test/unit' +require 'kgio' + +class TestTFO < Test::Unit::TestCase + def test_constants + if `uname -s`.chomp == "Linux" && `uname -r`.to_f >= 3.7 + assert_equal 23, Kgio::TCP_FASTOPEN + assert_equal 0x20000000, Kgio::MSG_FASTOPEN + end + end + + def fastopen_ok? + if RUBY_PLATFORM =~ /linux/ + tfo = File.read("/proc/sys/net/ipv4/tcp_fastopen").to_i + client_enable = 1 + server_enable = 2 + enable = client_enable | server_enable + (tfo & enable) == enable + else + false + end + end + + def test_tfo_client_server + unless fastopen_ok? + warn "TCP Fast Open not enabled on this system (check kernel docs)" + return + end + addr = '127.0.0.1' + qlen = 1024 + s = Kgio::TCPServer.new(addr, 0) + s.setsockopt(:TCP, Kgio::TCP_FASTOPEN, qlen) + port = s.local_address.ip_port + addr = Socket.pack_sockaddr_in(port, addr) + c = Kgio::Socket.new(:INET, :STREAM) + assert_nil c.fastopen("HELLO", addr) + a = s.accept + assert_equal "HELLO", a.read(5) + c.close + a.close + + # ensure empty sends work + c = Kgio::Socket.new(:INET, :STREAM) + assert_nil c.fastopen("", addr) + a = s.accept + Thread.new { c.close } + assert_nil a.read(1) + a.close + + # try a monster packet + buf = 'x' * (1024 * 1024 * 320) + + c = Kgio::Socket.new(:INET, :STREAM) + thr = Thread.new do + a = s.accept + assert_equal buf.size, a.read(buf.size).size + a.close + end + assert_nil c.fastopen(buf, addr) + thr.join + c.close + + # allow timeouts + c = Kgio::Socket.new(:INET, :STREAM) + c.setsockopt(:SOCKET, :SNDTIMEO, [ 0, 10 ].pack("l_l_")) + unsent = c.fastopen(buf, addr) + c.close + assert_equal s.accept.read.size + unsent.size, buf.size + end if defined?(Addrinfo) && defined?(Kgio::TCP_FASTOPEN) +end |