2015-12-16 00:07:31 -05:00
|
|
|
# frozen_string_literal: false
|
2010-12-10 20:25:25 -05:00
|
|
|
require_relative 'utils'
|
2016-08-29 01:47:09 -04:00
|
|
|
require_relative 'ut_eof'
|
2005-03-05 16:36:11 -05:00
|
|
|
|
2017-09-03 08:35:27 -04:00
|
|
|
if defined?(OpenSSL)
|
|
|
|
|
2014-05-07 19:21:10 -04:00
|
|
|
module OpenSSL::SSLPairM
|
2017-09-03 08:35:27 -04:00
|
|
|
def setup
|
|
|
|
svr_dn = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost")
|
|
|
|
ee_exts = [
|
|
|
|
["keyUsage", "keyEncipherment,digitalSignature", true],
|
|
|
|
]
|
|
|
|
@svr_key = OpenSSL::TestUtils::Fixtures.pkey("rsa1024")
|
|
|
|
@svr_cert = issue_cert(svr_dn, @svr_key, 1, ee_exts, nil, nil)
|
2005-03-05 16:36:11 -05:00
|
|
|
end
|
|
|
|
|
2017-09-03 08:35:27 -04:00
|
|
|
def ssl_pair
|
2005-03-05 16:36:11 -05:00
|
|
|
host = "127.0.0.1"
|
2017-09-03 08:35:27 -04:00
|
|
|
tcps = create_tcp_server(host, 0)
|
|
|
|
port = tcps.connect_address.ip_port
|
2005-03-05 16:36:11 -05:00
|
|
|
|
|
|
|
th = Thread.new {
|
2017-09-03 08:35:27 -04:00
|
|
|
sctx = OpenSSL::SSL::SSLContext.new
|
|
|
|
sctx.cert = @svr_cert
|
|
|
|
sctx.key = @svr_key
|
|
|
|
sctx.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey_dh("dh1024") }
|
2017-09-12 09:52:51 -04:00
|
|
|
sctx.options |= OpenSSL::SSL::OP_NO_COMPRESSION
|
2017-09-03 08:35:27 -04:00
|
|
|
ssls = OpenSSL::SSL::SSLServer.new(tcps, sctx)
|
2005-03-05 16:36:11 -05:00
|
|
|
ns = ssls.accept
|
|
|
|
ssls.close
|
|
|
|
ns
|
|
|
|
}
|
2017-09-03 08:35:27 -04:00
|
|
|
|
|
|
|
tcpc = create_tcp_client(host, port)
|
|
|
|
c = OpenSSL::SSL::SSLSocket.new(tcpc)
|
|
|
|
c.connect
|
2005-03-05 16:36:11 -05:00
|
|
|
s = th.value
|
2017-09-03 08:35:27 -04:00
|
|
|
|
|
|
|
yield c, s
|
2007-12-15 10:00:52 -05:00
|
|
|
ensure
|
2017-09-03 08:35:27 -04:00
|
|
|
tcpc&.close
|
|
|
|
tcps&.close
|
|
|
|
s&.close
|
2005-03-05 16:36:11 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-05-07 19:21:10 -04:00
|
|
|
module OpenSSL::SSLPair
|
|
|
|
include OpenSSL::SSLPairM
|
2014-05-07 08:48:27 -04:00
|
|
|
|
2014-05-07 19:21:10 -04:00
|
|
|
def create_tcp_server(host, port)
|
|
|
|
TCPServer.new(host, port)
|
2014-05-07 08:48:27 -04:00
|
|
|
end
|
|
|
|
|
2014-05-07 19:21:10 -04:00
|
|
|
def create_tcp_client(host, port)
|
|
|
|
TCPSocket.new(host, port)
|
2014-05-07 08:48:27 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-05-07 19:21:10 -04:00
|
|
|
module OpenSSL::SSLPairLowlevelSocket
|
|
|
|
include OpenSSL::SSLPairM
|
|
|
|
|
|
|
|
def create_tcp_server(host, port)
|
|
|
|
Addrinfo.tcp(host, port).listen
|
|
|
|
end
|
2005-03-05 16:36:11 -05:00
|
|
|
|
2014-05-07 19:21:10 -04:00
|
|
|
def create_tcp_client(host, port)
|
|
|
|
Addrinfo.tcp(host, port).connect
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module OpenSSL::TestEOF1M
|
2005-03-05 16:36:11 -05:00
|
|
|
def open_file(content)
|
2017-09-03 08:35:27 -04:00
|
|
|
ssl_pair { |s1, s2|
|
|
|
|
begin
|
|
|
|
th = Thread.new { s2 << content; s2.close }
|
|
|
|
yield s1
|
|
|
|
ensure
|
|
|
|
th&.join
|
|
|
|
end
|
|
|
|
}
|
2005-03-05 16:36:11 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-05-07 19:21:10 -04:00
|
|
|
module OpenSSL::TestEOF2M
|
2005-03-05 16:36:11 -05:00
|
|
|
def open_file(content)
|
2017-09-03 08:35:27 -04:00
|
|
|
ssl_pair { |s1, s2|
|
|
|
|
begin
|
|
|
|
th = Thread.new { s1 << content; s1.close }
|
|
|
|
yield s2
|
|
|
|
ensure
|
|
|
|
th&.join
|
|
|
|
end
|
|
|
|
}
|
2005-03-05 16:36:11 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-05-07 19:21:10 -04:00
|
|
|
module OpenSSL::TestPairM
|
2005-03-05 16:36:11 -05:00
|
|
|
def test_getc
|
|
|
|
ssl_pair {|s1, s2|
|
|
|
|
s1 << "a"
|
|
|
|
assert_equal(?a, s2.getc)
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2016-09-07 21:09:19 -04:00
|
|
|
def test_gets
|
|
|
|
ssl_pair {|s1, s2|
|
|
|
|
s1 << "abc\n\n$def123ghi"
|
|
|
|
s1.close
|
|
|
|
ret = s2.gets
|
|
|
|
assert_equal Encoding::BINARY, ret.encoding
|
|
|
|
assert_equal "abc\n", ret
|
|
|
|
assert_equal "\n$", s2.gets("$")
|
|
|
|
assert_equal "def123", s2.gets(/\d+/)
|
|
|
|
assert_equal "ghi", s2.gets
|
|
|
|
assert_equal nil, s2.gets
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2015-08-01 18:08:17 -04:00
|
|
|
def test_gets_eof_limit
|
|
|
|
ssl_pair {|s1, s2|
|
|
|
|
s1.write("hello")
|
|
|
|
s1.close # trigger EOF
|
2016-09-07 21:09:19 -04:00
|
|
|
assert_match "hello", s2.gets("\n", 6), "[ruby-core:70149] [Bug #11400]"
|
2015-08-01 18:08:17 -04:00
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2005-03-05 16:36:11 -05:00
|
|
|
def test_readpartial
|
|
|
|
ssl_pair {|s1, s2|
|
|
|
|
s2.write "a\nbcd"
|
|
|
|
assert_equal("a\n", s1.gets)
|
2014-05-27 06:03:09 -04:00
|
|
|
result = ""
|
|
|
|
result << s1.readpartial(10) until result.length == 3
|
|
|
|
assert_equal("bcd", result)
|
2005-03-05 16:36:11 -05:00
|
|
|
s2.write "efg"
|
2014-05-27 06:03:09 -04:00
|
|
|
result = ""
|
|
|
|
result << s1.readpartial(10) until result.length == 3
|
|
|
|
assert_equal("efg", result)
|
2005-03-05 16:36:11 -05:00
|
|
|
s2.close
|
|
|
|
assert_raise(EOFError) { s1.readpartial(10) }
|
|
|
|
assert_raise(EOFError) { s1.readpartial(10) }
|
|
|
|
assert_equal("", s1.readpartial(0))
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_readall
|
|
|
|
ssl_pair {|s1, s2|
|
|
|
|
s2.close
|
|
|
|
assert_equal("", s1.read)
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_readline
|
|
|
|
ssl_pair {|s1, s2|
|
|
|
|
s2.close
|
|
|
|
assert_raise(EOFError) { s1.readline }
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_puts_meta
|
|
|
|
ssl_pair {|s1, s2|
|
|
|
|
begin
|
|
|
|
old = $/
|
|
|
|
$/ = '*'
|
|
|
|
s1.puts 'a'
|
|
|
|
ensure
|
|
|
|
$/ = old
|
|
|
|
end
|
|
|
|
s1.close
|
|
|
|
assert_equal("a\n", s2.read)
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_puts_empty
|
|
|
|
ssl_pair {|s1, s2|
|
|
|
|
s1.puts
|
|
|
|
s1.close
|
|
|
|
assert_equal("\n", s2.read)
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2017-09-03 08:35:27 -04:00
|
|
|
def test_multibyte_read_write
|
|
|
|
# German a umlaut
|
|
|
|
auml = [%w{ C3 A4 }.join('')].pack('H*')
|
|
|
|
auml.force_encoding(Encoding::UTF_8)
|
|
|
|
bsize = auml.bytesize
|
|
|
|
|
|
|
|
ssl_pair { |s1, s2|
|
|
|
|
assert_equal bsize, s1.write(auml)
|
|
|
|
read = s2.read(bsize)
|
|
|
|
assert_equal Encoding::ASCII_8BIT, read.encoding
|
|
|
|
assert_equal bsize, read.bytesize
|
|
|
|
assert_equal auml, read.force_encoding(Encoding::UTF_8)
|
|
|
|
|
|
|
|
s1.puts(auml)
|
|
|
|
read = s2.gets
|
|
|
|
assert_equal Encoding::ASCII_8BIT, read.encoding
|
|
|
|
assert_equal bsize + 1, read.bytesize
|
|
|
|
assert_equal auml + "\n", read.force_encoding(Encoding::UTF_8)
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2008-12-28 11:09:59 -05:00
|
|
|
def test_read_nonblock
|
|
|
|
ssl_pair {|s1, s2|
|
2008-12-31 03:18:12 -05:00
|
|
|
err = nil
|
2013-04-08 15:58:55 -04:00
|
|
|
assert_raise(OpenSSL::SSL::SSLErrorWaitReadable) {
|
2008-12-31 03:18:12 -05:00
|
|
|
begin
|
|
|
|
s2.read_nonblock(10)
|
|
|
|
ensure
|
|
|
|
err = $!
|
|
|
|
end
|
|
|
|
}
|
2009-03-19 07:40:38 -04:00
|
|
|
assert_kind_of(IO::WaitReadable, err)
|
2008-12-28 11:09:59 -05:00
|
|
|
s1.write "abc\ndef\n"
|
2009-02-07 21:01:22 -05:00
|
|
|
IO.select([s2])
|
2008-12-28 11:09:59 -05:00
|
|
|
assert_equal("ab", s2.read_nonblock(2))
|
|
|
|
assert_equal("c\n", s2.gets)
|
|
|
|
ret = nil
|
|
|
|
assert_nothing_raised("[ruby-core:20298]") { ret = s2.read_nonblock(10) }
|
|
|
|
assert_equal("def\n", ret)
|
2013-08-26 18:41:44 -04:00
|
|
|
s1.close
|
2017-09-24 12:26:22 -04:00
|
|
|
IO.select([s2])
|
2013-08-26 18:41:44 -04:00
|
|
|
assert_raise(EOFError) { s2.read_nonblock(10) }
|
2008-12-28 11:09:59 -05:00
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2013-08-26 18:41:44 -04:00
|
|
|
def test_read_nonblock_no_exception
|
|
|
|
ssl_pair {|s1, s2|
|
|
|
|
assert_equal :wait_readable, s2.read_nonblock(10, exception: false)
|
|
|
|
s1.write "abc\ndef\n"
|
|
|
|
IO.select([s2])
|
|
|
|
assert_equal("ab", s2.read_nonblock(2, exception: false))
|
|
|
|
assert_equal("c\n", s2.gets)
|
|
|
|
ret = nil
|
|
|
|
assert_nothing_raised("[ruby-core:20298]") { ret = s2.read_nonblock(10, exception: false) }
|
|
|
|
assert_equal("def\n", ret)
|
|
|
|
s1.close
|
2017-09-24 12:26:22 -04:00
|
|
|
IO.select([s2])
|
2013-08-26 18:41:44 -04:00
|
|
|
assert_equal(nil, s2.read_nonblock(10, exception: false))
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2017-09-24 12:26:22 -04:00
|
|
|
def test_read_with_outbuf
|
|
|
|
ssl_pair { |s1, s2|
|
|
|
|
s1.write("abc\n")
|
|
|
|
buf = ""
|
|
|
|
ret = s2.read(2, buf)
|
|
|
|
assert_same ret, buf
|
|
|
|
assert_equal "ab", ret
|
|
|
|
|
|
|
|
buf = "garbage"
|
|
|
|
ret = s2.read(2, buf)
|
|
|
|
assert_same ret, buf
|
|
|
|
assert_equal "c\n", ret
|
|
|
|
|
|
|
|
buf = "garbage"
|
|
|
|
assert_equal :wait_readable, s2.read_nonblock(100, buf, exception: false)
|
|
|
|
assert_equal "", buf
|
|
|
|
|
|
|
|
s1.close
|
|
|
|
buf = "garbage"
|
|
|
|
assert_equal nil, s2.read(100, buf)
|
|
|
|
assert_equal "", buf
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2009-03-20 13:39:44 -04:00
|
|
|
def test_write_nonblock
|
|
|
|
ssl_pair {|s1, s2|
|
2017-09-05 05:47:59 -04:00
|
|
|
assert_equal 3, s1.write_nonblock("foo")
|
|
|
|
assert_equal "foo", s2.read(3)
|
|
|
|
|
|
|
|
data = "x" * 16384
|
|
|
|
written = 0
|
|
|
|
while true
|
|
|
|
begin
|
|
|
|
written += s1.write_nonblock(data)
|
|
|
|
rescue IO::WaitWritable, IO::WaitReadable
|
|
|
|
break
|
|
|
|
end
|
2009-03-20 13:39:44 -04:00
|
|
|
end
|
2017-09-05 05:47:59 -04:00
|
|
|
assert written > 0
|
|
|
|
assert_equal written, s2.read(written).bytesize
|
2009-03-20 13:39:44 -04:00
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2013-08-26 18:41:44 -04:00
|
|
|
def test_write_nonblock_no_exceptions
|
|
|
|
ssl_pair {|s1, s2|
|
2017-09-05 05:47:59 -04:00
|
|
|
assert_equal 3, s1.write_nonblock("foo", exception: false)
|
|
|
|
assert_equal "foo", s2.read(3)
|
|
|
|
|
|
|
|
data = "x" * 16384
|
|
|
|
written = 0
|
|
|
|
while true
|
|
|
|
case ret = s1.write_nonblock(data, exception: false)
|
|
|
|
when :wait_readable, :wait_writable
|
|
|
|
break
|
|
|
|
else
|
|
|
|
written += ret
|
|
|
|
end
|
|
|
|
end
|
|
|
|
assert written > 0
|
|
|
|
assert_equal written, s2.read(written).bytesize
|
2013-08-26 18:41:44 -04:00
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2009-03-20 13:39:44 -04:00
|
|
|
def test_write_nonblock_with_buffered_data
|
|
|
|
ssl_pair {|s1, s2|
|
|
|
|
s1.write "foo"
|
|
|
|
s1.write_nonblock("bar")
|
|
|
|
s1.write "baz"
|
|
|
|
s1.close
|
|
|
|
assert_equal("foobarbaz", s2.read)
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2013-08-26 18:41:44 -04:00
|
|
|
def test_write_nonblock_with_buffered_data_no_exceptions
|
|
|
|
ssl_pair {|s1, s2|
|
|
|
|
s1.write "foo"
|
|
|
|
s1.write_nonblock("bar", exception: false)
|
|
|
|
s1.write "baz"
|
|
|
|
s1.close
|
|
|
|
assert_equal("foobarbaz", s2.read)
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2016-03-31 16:33:55 -04:00
|
|
|
def test_write_nonblock_retry
|
|
|
|
ssl_pair {|s1, s2|
|
|
|
|
# fill up a socket so we hit EAGAIN
|
|
|
|
written = String.new
|
|
|
|
n = 0
|
2016-12-10 03:12:02 -05:00
|
|
|
buf = 'a' * 4099
|
2016-03-31 16:33:55 -04:00
|
|
|
case ret = s1.write_nonblock(buf, exception: false)
|
|
|
|
when :wait_readable then break
|
|
|
|
when :wait_writable then break
|
|
|
|
when Integer
|
|
|
|
written << buf
|
|
|
|
n += ret
|
|
|
|
exp = buf.bytesize
|
|
|
|
if ret != exp
|
|
|
|
buf = buf.byteslice(ret, exp - ret)
|
|
|
|
end
|
|
|
|
end while true
|
|
|
|
assert_kind_of Symbol, ret
|
|
|
|
|
|
|
|
# make more space for subsequent write:
|
|
|
|
readed = s2.read(n)
|
|
|
|
assert_equal written, readed
|
|
|
|
|
|
|
|
# this fails if SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is missing:
|
|
|
|
buf2 = Marshal.load(Marshal.dump(buf))
|
|
|
|
assert_kind_of Integer, s1.write_nonblock(buf2, exception: false)
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2016-08-06 17:50:10 -04:00
|
|
|
def test_write_zero
|
|
|
|
ssl_pair {|s1, s2|
|
|
|
|
assert_equal 0, s2.write_nonblock('', exception: false)
|
|
|
|
assert_kind_of Symbol, s1.read_nonblock(1, exception: false)
|
|
|
|
assert_equal 0, s2.syswrite('')
|
|
|
|
assert_kind_of Symbol, s1.read_nonblock(1, exception: false)
|
|
|
|
assert_equal 0, s2.write('')
|
|
|
|
assert_kind_of Symbol, s1.read_nonblock(1, exception: false)
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2017-11-25 09:12:08 -05:00
|
|
|
def test_write_multiple_arguments
|
|
|
|
ssl_pair {|s1, s2|
|
|
|
|
str1 = "foo"; str2 = "bar"
|
|
|
|
assert_equal 6, s1.write(str1, str2)
|
|
|
|
s1.close
|
|
|
|
assert_equal "foobar", s2.read
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2016-08-29 01:47:09 -04:00
|
|
|
def test_partial_tls_record_read_nonblock
|
|
|
|
ssl_pair { |s1, s2|
|
|
|
|
# the beginning of a TLS record
|
|
|
|
s1.io.write("\x17")
|
|
|
|
# should raise a IO::WaitReadable since a full TLS record is not available
|
|
|
|
# for reading
|
|
|
|
assert_raise(IO::WaitReadable) { s2.read_nonblock(1) }
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2014-05-07 08:22:02 -04:00
|
|
|
def tcp_pair
|
2009-03-21 02:56:33 -04:00
|
|
|
host = "127.0.0.1"
|
2014-05-07 08:22:02 -04:00
|
|
|
serv = TCPServer.new(host, 0)
|
2009-03-21 02:56:33 -04:00
|
|
|
port = serv.connect_address.ip_port
|
|
|
|
sock1 = TCPSocket.new(host, port)
|
|
|
|
sock2 = serv.accept
|
|
|
|
serv.close
|
2014-05-07 08:22:02 -04:00
|
|
|
[sock1, sock2]
|
|
|
|
ensure
|
|
|
|
serv.close if serv && !serv.closed?
|
|
|
|
end
|
|
|
|
|
connect_nonblock supports "exception: false"
This is for consistency with accept_nonblock arguments and gives a
minor speedup from avoiding exceptions.
[ruby-core:68838] [Feature #11024]
* ext/openssl/ossl_ssl.c (ossl_ssl_connect_nonblock):
support `exception: false'
* (get_no_exception): move function location
* ext/socket/socket.c (sock_connect_nonblock):
support `exception: false'
* test/openssl/test_pair.rb (test_connect_accept_nonblock_no_exception):
test `exception: false' on connect,
rename from `test_accept_nonblock_no_exception'
* test/socket/test_nonblock.rb (test_connect_nonblock_no_exception):
new test
Benchmark results:
default 0.050000 0.100000 0.150000 ( 0.151307)
exception: false 0.030000 0.080000 0.110000 ( 0.108840)
----------------------------8<-----------------------
require 'socket'
require 'benchmark'
require 'io/wait'
require 'tmpdir'
host = '127.0.0.1'
serv = TCPServer.new(host, 0) # UNIX sockets may not hit EINPROGRESS
nr = 5000 # few iterations to avoid running out of ports
addr = serv.getsockname
pid = fork do
begin
serv.accept.close
rescue => e
warn "#$$: #{e.message} (#{e.class})"
end while true
end
at_exit { Process.kill(:TERM, pid) }
serv.close
Benchmark.bmbm do |x|
x.report("default") do
nr.times do
s = Socket.new(:INET, :STREAM)
s.setsockopt(:SOL_SOCKET, :SO_REUSEADDR, 1)
begin
s.connect_nonblock(addr)
rescue IO::WaitWritable
s.wait_writable
end
s.close
end
end
x.report("exception: false") do
nr.times do
s = Socket.new(:INET, :STREAM)
s.setsockopt(:SOL_SOCKET, :SO_REUSEADDR, 1)
case s.connect_nonblock(addr, exception: false)
when :wait_writable
s.wait_writable
end
s.close
end
end
end
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50254 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-04-11 21:41:51 -04:00
|
|
|
def test_connect_accept_nonblock_no_exception
|
2015-03-11 23:03:04 -04:00
|
|
|
ctx2 = OpenSSL::SSL::SSLContext.new
|
2017-09-03 08:35:27 -04:00
|
|
|
ctx2.cert = @svr_cert
|
|
|
|
ctx2.key = @svr_key
|
|
|
|
ctx2.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey_dh("dh1024") }
|
2015-03-11 23:03:04 -04:00
|
|
|
|
|
|
|
sock1, sock2 = tcp_pair
|
|
|
|
|
|
|
|
s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2)
|
|
|
|
accepted = s2.accept_nonblock(exception: false)
|
|
|
|
assert_equal :wait_readable, accepted
|
|
|
|
|
|
|
|
ctx1 = OpenSSL::SSL::SSLContext.new
|
|
|
|
s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1)
|
connect_nonblock supports "exception: false"
This is for consistency with accept_nonblock arguments and gives a
minor speedup from avoiding exceptions.
[ruby-core:68838] [Feature #11024]
* ext/openssl/ossl_ssl.c (ossl_ssl_connect_nonblock):
support `exception: false'
* (get_no_exception): move function location
* ext/socket/socket.c (sock_connect_nonblock):
support `exception: false'
* test/openssl/test_pair.rb (test_connect_accept_nonblock_no_exception):
test `exception: false' on connect,
rename from `test_accept_nonblock_no_exception'
* test/socket/test_nonblock.rb (test_connect_nonblock_no_exception):
new test
Benchmark results:
default 0.050000 0.100000 0.150000 ( 0.151307)
exception: false 0.030000 0.080000 0.110000 ( 0.108840)
----------------------------8<-----------------------
require 'socket'
require 'benchmark'
require 'io/wait'
require 'tmpdir'
host = '127.0.0.1'
serv = TCPServer.new(host, 0) # UNIX sockets may not hit EINPROGRESS
nr = 5000 # few iterations to avoid running out of ports
addr = serv.getsockname
pid = fork do
begin
serv.accept.close
rescue => e
warn "#$$: #{e.message} (#{e.class})"
end while true
end
at_exit { Process.kill(:TERM, pid) }
serv.close
Benchmark.bmbm do |x|
x.report("default") do
nr.times do
s = Socket.new(:INET, :STREAM)
s.setsockopt(:SOL_SOCKET, :SO_REUSEADDR, 1)
begin
s.connect_nonblock(addr)
rescue IO::WaitWritable
s.wait_writable
end
s.close
end
end
x.report("exception: false") do
nr.times do
s = Socket.new(:INET, :STREAM)
s.setsockopt(:SOL_SOCKET, :SO_REUSEADDR, 1)
case s.connect_nonblock(addr, exception: false)
when :wait_writable
s.wait_writable
end
s.close
end
end
end
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50254 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-04-11 21:41:51 -04:00
|
|
|
th = Thread.new do
|
|
|
|
rets = []
|
|
|
|
begin
|
|
|
|
rv = s1.connect_nonblock(exception: false)
|
|
|
|
rets << rv
|
|
|
|
case rv
|
|
|
|
when :wait_writable
|
|
|
|
IO.select(nil, [s1], nil, 5)
|
|
|
|
when :wait_readable
|
|
|
|
IO.select([s1], nil, nil, 5)
|
|
|
|
end
|
|
|
|
end until rv == s1
|
|
|
|
rets
|
|
|
|
end
|
|
|
|
|
2015-03-11 23:03:04 -04:00
|
|
|
until th.join(0.01)
|
|
|
|
accepted = s2.accept_nonblock(exception: false)
|
2016-07-26 09:02:33 -04:00
|
|
|
assert_include([s2, :wait_readable, :wait_writable ], accepted)
|
2015-03-11 23:03:04 -04:00
|
|
|
end
|
connect_nonblock supports "exception: false"
This is for consistency with accept_nonblock arguments and gives a
minor speedup from avoiding exceptions.
[ruby-core:68838] [Feature #11024]
* ext/openssl/ossl_ssl.c (ossl_ssl_connect_nonblock):
support `exception: false'
* (get_no_exception): move function location
* ext/socket/socket.c (sock_connect_nonblock):
support `exception: false'
* test/openssl/test_pair.rb (test_connect_accept_nonblock_no_exception):
test `exception: false' on connect,
rename from `test_accept_nonblock_no_exception'
* test/socket/test_nonblock.rb (test_connect_nonblock_no_exception):
new test
Benchmark results:
default 0.050000 0.100000 0.150000 ( 0.151307)
exception: false 0.030000 0.080000 0.110000 ( 0.108840)
----------------------------8<-----------------------
require 'socket'
require 'benchmark'
require 'io/wait'
require 'tmpdir'
host = '127.0.0.1'
serv = TCPServer.new(host, 0) # UNIX sockets may not hit EINPROGRESS
nr = 5000 # few iterations to avoid running out of ports
addr = serv.getsockname
pid = fork do
begin
serv.accept.close
rescue => e
warn "#$$: #{e.message} (#{e.class})"
end while true
end
at_exit { Process.kill(:TERM, pid) }
serv.close
Benchmark.bmbm do |x|
x.report("default") do
nr.times do
s = Socket.new(:INET, :STREAM)
s.setsockopt(:SOL_SOCKET, :SO_REUSEADDR, 1)
begin
s.connect_nonblock(addr)
rescue IO::WaitWritable
s.wait_writable
end
s.close
end
end
x.report("exception: false") do
nr.times do
s = Socket.new(:INET, :STREAM)
s.setsockopt(:SOL_SOCKET, :SO_REUSEADDR, 1)
case s.connect_nonblock(addr, exception: false)
when :wait_writable
s.wait_writable
end
s.close
end
end
end
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50254 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-04-11 21:41:51 -04:00
|
|
|
|
|
|
|
rets = th.value
|
|
|
|
assert_instance_of Array, rets
|
|
|
|
rets.each do |rv|
|
2016-07-26 09:02:33 -04:00
|
|
|
assert_include([s1, :wait_readable, :wait_writable ], rv)
|
connect_nonblock supports "exception: false"
This is for consistency with accept_nonblock arguments and gives a
minor speedup from avoiding exceptions.
[ruby-core:68838] [Feature #11024]
* ext/openssl/ossl_ssl.c (ossl_ssl_connect_nonblock):
support `exception: false'
* (get_no_exception): move function location
* ext/socket/socket.c (sock_connect_nonblock):
support `exception: false'
* test/openssl/test_pair.rb (test_connect_accept_nonblock_no_exception):
test `exception: false' on connect,
rename from `test_accept_nonblock_no_exception'
* test/socket/test_nonblock.rb (test_connect_nonblock_no_exception):
new test
Benchmark results:
default 0.050000 0.100000 0.150000 ( 0.151307)
exception: false 0.030000 0.080000 0.110000 ( 0.108840)
----------------------------8<-----------------------
require 'socket'
require 'benchmark'
require 'io/wait'
require 'tmpdir'
host = '127.0.0.1'
serv = TCPServer.new(host, 0) # UNIX sockets may not hit EINPROGRESS
nr = 5000 # few iterations to avoid running out of ports
addr = serv.getsockname
pid = fork do
begin
serv.accept.close
rescue => e
warn "#$$: #{e.message} (#{e.class})"
end while true
end
at_exit { Process.kill(:TERM, pid) }
serv.close
Benchmark.bmbm do |x|
x.report("default") do
nr.times do
s = Socket.new(:INET, :STREAM)
s.setsockopt(:SOL_SOCKET, :SO_REUSEADDR, 1)
begin
s.connect_nonblock(addr)
rescue IO::WaitWritable
s.wait_writable
end
s.close
end
end
x.report("exception: false") do
nr.times do
s = Socket.new(:INET, :STREAM)
s.setsockopt(:SOL_SOCKET, :SO_REUSEADDR, 1)
case s.connect_nonblock(addr, exception: false)
when :wait_writable
s.wait_writable
end
s.close
end
end
end
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50254 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-04-11 21:41:51 -04:00
|
|
|
end
|
2015-03-11 23:03:04 -04:00
|
|
|
ensure
|
2015-07-30 00:43:23 -04:00
|
|
|
th.join if th
|
2015-03-11 23:03:04 -04:00
|
|
|
s1.close if s1
|
|
|
|
s2.close if s2
|
|
|
|
sock1.close if sock1
|
|
|
|
sock2.close if sock2
|
|
|
|
accepted.close if accepted.respond_to?(:close)
|
|
|
|
end
|
|
|
|
|
2014-05-07 08:22:02 -04:00
|
|
|
def test_connect_accept_nonblock
|
|
|
|
ctx = OpenSSL::SSL::SSLContext.new()
|
2017-09-03 08:35:27 -04:00
|
|
|
ctx.cert = @svr_cert
|
|
|
|
ctx.key = @svr_key
|
|
|
|
ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey_dh("dh1024") }
|
2014-05-07 08:22:02 -04:00
|
|
|
|
|
|
|
sock1, sock2 = tcp_pair
|
2009-03-21 02:56:33 -04:00
|
|
|
|
|
|
|
th = Thread.new {
|
|
|
|
s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx)
|
|
|
|
s2.sync_close = true
|
|
|
|
begin
|
|
|
|
sleep 0.2
|
|
|
|
s2.accept_nonblock
|
|
|
|
rescue IO::WaitReadable
|
|
|
|
IO.select([s2])
|
|
|
|
retry
|
|
|
|
rescue IO::WaitWritable
|
|
|
|
IO.select(nil, [s2])
|
|
|
|
retry
|
|
|
|
end
|
|
|
|
s2
|
|
|
|
}
|
|
|
|
|
|
|
|
sleep 0.1
|
|
|
|
ctx = OpenSSL::SSL::SSLContext.new()
|
|
|
|
s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx)
|
|
|
|
begin
|
|
|
|
sleep 0.2
|
|
|
|
s1.connect_nonblock
|
|
|
|
rescue IO::WaitReadable
|
|
|
|
IO.select([s1])
|
|
|
|
retry
|
|
|
|
rescue IO::WaitWritable
|
|
|
|
IO.select(nil, [s1])
|
|
|
|
retry
|
|
|
|
end
|
|
|
|
s1.sync_close = true
|
|
|
|
|
|
|
|
s2 = th.value
|
|
|
|
|
|
|
|
s1.print "a\ndef"
|
|
|
|
assert_equal("a\n", s2.gets)
|
|
|
|
ensure
|
2015-07-30 00:43:23 -04:00
|
|
|
th.join if th
|
2011-07-14 01:41:05 -04:00
|
|
|
s1.close if s1 && !s1.closed?
|
|
|
|
s2.close if s2 && !s2.closed?
|
2009-03-21 02:56:33 -04:00
|
|
|
sock1.close if sock1 && !sock1.closed?
|
|
|
|
sock2.close if sock2 && !sock2.closed?
|
|
|
|
end
|
2014-05-07 19:21:10 -04:00
|
|
|
end
|
2009-03-21 02:56:33 -04:00
|
|
|
|
2016-05-18 00:07:47 -04:00
|
|
|
class OpenSSL::TestEOF1 < OpenSSL::TestCase
|
2016-11-05 03:10:05 -04:00
|
|
|
include OpenSSL::TestEOF
|
2014-05-07 19:21:10 -04:00
|
|
|
include OpenSSL::SSLPair
|
|
|
|
include OpenSSL::TestEOF1M
|
2005-03-05 16:36:11 -05:00
|
|
|
end
|
|
|
|
|
2016-05-18 00:07:47 -04:00
|
|
|
class OpenSSL::TestEOF1LowlevelSocket < OpenSSL::TestCase
|
2016-11-05 03:10:05 -04:00
|
|
|
include OpenSSL::TestEOF
|
2014-05-07 19:21:10 -04:00
|
|
|
include OpenSSL::SSLPairLowlevelSocket
|
|
|
|
include OpenSSL::TestEOF1M
|
|
|
|
end
|
2014-05-07 08:48:27 -04:00
|
|
|
|
2016-05-18 00:07:47 -04:00
|
|
|
class OpenSSL::TestEOF2 < OpenSSL::TestCase
|
2016-11-05 03:10:05 -04:00
|
|
|
include OpenSSL::TestEOF
|
2014-05-07 19:21:10 -04:00
|
|
|
include OpenSSL::SSLPair
|
|
|
|
include OpenSSL::TestEOF2M
|
|
|
|
end
|
|
|
|
|
2016-05-18 00:07:47 -04:00
|
|
|
class OpenSSL::TestEOF2LowlevelSocket < OpenSSL::TestCase
|
2016-11-05 03:10:05 -04:00
|
|
|
include OpenSSL::TestEOF
|
2014-05-07 19:21:10 -04:00
|
|
|
include OpenSSL::SSLPairLowlevelSocket
|
|
|
|
include OpenSSL::TestEOF2M
|
|
|
|
end
|
|
|
|
|
2016-05-18 00:07:47 -04:00
|
|
|
class OpenSSL::TestPair < OpenSSL::TestCase
|
2014-05-07 19:21:10 -04:00
|
|
|
include OpenSSL::SSLPair
|
|
|
|
include OpenSSL::TestPairM
|
|
|
|
end
|
|
|
|
|
2016-05-18 00:07:47 -04:00
|
|
|
class OpenSSL::TestPairLowlevelSocket < OpenSSL::TestCase
|
2014-05-07 19:21:10 -04:00
|
|
|
include OpenSSL::SSLPairLowlevelSocket
|
|
|
|
include OpenSSL::TestPairM
|
2014-05-07 08:48:27 -04:00
|
|
|
end
|
|
|
|
|
2005-03-05 16:36:11 -05:00
|
|
|
end
|