diff options
author | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2009-03-21 06:56:33 +0000 |
---|---|---|
committer | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2009-03-21 06:56:33 +0000 |
commit | 7fd155cf0f088f763dfb6353f251319775549b77 (patch) | |
tree | 7c0753f342b346115e93de4a40442b32b9879c9e | |
parent | f65d706529969593b318e79ca26bf03c11b6347b (diff) | |
download | ruby-7fd155cf0f088f763dfb6353f251319775549b77.tar.gz |
* ext/openssl/ossl_ssl.c (write_would_block): defined.
(read_would_block): defined.
(ossl_start_ssl): add nonblock argument.
(ossl_ssl_connect): follow ossl_start_ssl change.
(ossl_ssl_connect_nonblock): new method.
(ossl_ssl_accept): follow ossl_start_ssl change.
(ossl_ssl_accept_nonblock): new method.
(ossl_ssl_read_internal): use write_would_block and
read_would_block.
(ossl_ssl_write_internal): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@23029 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | ext/openssl/ossl_ssl.c | 76 | ||||
-rw-r--r-- | test/openssl/test_pair.rb | 56 |
4 files changed, 126 insertions, 24 deletions
@@ -1,3 +1,16 @@ +Sat Mar 21 15:54:41 2009 Tanaka Akira <akr@fsij.org> + + * ext/openssl/ossl_ssl.c (write_would_block): defined. + (read_would_block): defined. + (ossl_start_ssl): add nonblock argument. + (ossl_ssl_connect): follow ossl_start_ssl change. + (ossl_ssl_connect_nonblock): new method. + (ossl_ssl_accept): follow ossl_start_ssl change. + (ossl_ssl_accept_nonblock): new method. + (ossl_ssl_read_internal): use write_would_block and + read_would_block. + (ossl_ssl_write_internal): ditto. + Sat Mar 21 08:19:52 2009 Nobuyoshi Nakada <nobu@ruby-lang.org> * process.c (rb_exec): prints error message only on platforms @@ -37,6 +37,7 @@ with all sufficient information, see the ChangeLog file. * new modules: * IO::WaitReadable * IO::WaitWritable + They are used to extend non-blocking exceptions. * Process * extended methods: @@ -91,9 +92,11 @@ with all sufficient information, see the ChangeLog file. * PTY.open * openssl - * new method: + * new methods: * OpenSSL::Buffering#read_nonblock * OpenSSL::Buffering#write_nonblock + * OpenSSL::SSL::SSLSocket#connect_nonblock + * OpenSSL::SSL::SSLSocket#accept_nonblock * socket diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 4c2477b16b..7575eca718 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -1020,8 +1020,28 @@ ossl_ssl_setup(VALUE self) #define ssl_get_error(ssl, ret) SSL_get_error(ssl, ret) #endif +static void +write_would_block(int nonblock) +{ + if (nonblock) { + VALUE exc = ossl_exc_new(eSSLError, "write would block"); + rb_extend_object(exc, rb_mWaitWritable); + rb_exc_raise(exc); + } +} + +static void +read_would_block(int nonblock) +{ + if (nonblock) { + VALUE exc = ossl_exc_new(eSSLError, "read would block"); + rb_extend_object(exc, rb_mWaitReadable); + rb_exc_raise(exc); + } +} + static VALUE -ossl_start_ssl(VALUE self, int (*func)(), const char *funcname) +ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, int nonblock) { SSL *ssl; rb_io_t *fptr; @@ -1044,9 +1064,11 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname) switch((ret2 = ssl_get_error(ssl, ret))){ case SSL_ERROR_WANT_WRITE: + write_would_block(nonblock); rb_io_wait_writable(FPTR_TO_FD(fptr)); continue; case SSL_ERROR_WANT_READ: + read_would_block(nonblock); rb_io_wait_readable(FPTR_TO_FD(fptr)); continue; case SSL_ERROR_SYSCALL: @@ -1068,7 +1090,18 @@ static VALUE ossl_ssl_connect(VALUE self) { ossl_ssl_setup(self); - return ossl_start_ssl(self, SSL_connect, "SSL_connect"); + return ossl_start_ssl(self, SSL_connect, "SSL_connect", 0); +} + +/* + * call-seq: + * ssl.connect_nonblock => self + */ +static VALUE +ossl_ssl_connect_nonblock(VALUE self) +{ + ossl_ssl_setup(self); + return ossl_start_ssl(self, SSL_connect, "SSL_connect", 1); } /* @@ -1079,7 +1112,18 @@ static VALUE ossl_ssl_accept(VALUE self) { ossl_ssl_setup(self); - return ossl_start_ssl(self, SSL_accept, "SSL_accept"); + return ossl_start_ssl(self, SSL_accept, "SSL_accept", 0); +} + +/* + * call-seq: + * ssl.accept_nonblock => self + */ +static VALUE +ossl_ssl_accept_nonblock(VALUE self) +{ + ossl_ssl_setup(self); + return ossl_start_ssl(self, SSL_accept, "SSL_accept", 1); } static VALUE @@ -1113,19 +1157,11 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) case SSL_ERROR_ZERO_RETURN: rb_eof_error(); case SSL_ERROR_WANT_WRITE: - if (nonblock) { - VALUE exc = ossl_exc_new(eSSLError, "write would block"); - rb_extend_object(exc, rb_mWaitWritable); - rb_exc_raise(exc); - } + write_would_block(nonblock); rb_io_wait_writable(FPTR_TO_FD(fptr)); continue; case SSL_ERROR_WANT_READ: - if (nonblock) { - VALUE exc = ossl_exc_new(eSSLError, "read would block"); - rb_extend_object(exc, rb_mWaitReadable); - rb_exc_raise(exc); - } + read_would_block(nonblock); rb_io_wait_readable(FPTR_TO_FD(fptr)); continue; case SSL_ERROR_SYSCALL: @@ -1198,19 +1234,11 @@ ossl_ssl_write_internal(VALUE self, VALUE str, int nonblock) case SSL_ERROR_NONE: goto end; case SSL_ERROR_WANT_WRITE: - if (nonblock) { - VALUE exc = ossl_exc_new(eSSLError, "write would block"); - rb_extend_object(exc, rb_mWaitWritable); - rb_exc_raise(exc); - } + write_would_block(nonblock); rb_io_wait_writable(FPTR_TO_FD(fptr)); continue; case SSL_ERROR_WANT_READ: - if (nonblock) { - VALUE exc = ossl_exc_new(eSSLError, "read would block"); - rb_extend_object(exc, rb_mWaitReadable); - rb_exc_raise(exc); - } + read_would_block(nonblock); rb_io_wait_readable(FPTR_TO_FD(fptr)); continue; case SSL_ERROR_SYSCALL: @@ -1566,7 +1594,9 @@ Init_ossl_ssl() rb_define_alias(cSSLSocket, "to_io", "io"); rb_define_method(cSSLSocket, "initialize", ossl_ssl_initialize, -1); rb_define_method(cSSLSocket, "connect", ossl_ssl_connect, 0); + rb_define_method(cSSLSocket, "connect_nonblock", ossl_ssl_connect_nonblock, 0); rb_define_method(cSSLSocket, "accept", ossl_ssl_accept, 0); + rb_define_method(cSSLSocket, "accept_nonblock", ossl_ssl_accept_nonblock, 0); rb_define_method(cSSLSocket, "sysread", ossl_ssl_read, -1); rb_define_private_method(cSSLSocket, "sysread_nonblock", ossl_ssl_read_nonblock, -1); rb_define_method(cSSLSocket, "syswrite", ossl_ssl_write, 1); diff --git a/test/openssl/test_pair.rb b/test/openssl/test_pair.rb index a6f1e4f55d..fb0662f501 100644 --- a/test/openssl/test_pair.rb +++ b/test/openssl/test_pair.rb @@ -192,6 +192,62 @@ class OpenSSL::TestPair < Test::Unit::TestCase } end + def test_connect_accept_nonblock + host = "127.0.0.1" + port = 0 + ctx = OpenSSL::SSL::SSLContext.new() + ctx.ciphers = "ADH" + serv = TCPServer.new(host, port) + ssls = OpenSSL::SSL::SSLServer.new(serv, ctx) + + port = serv.connect_address.ip_port + + sock1 = TCPSocket.new(host, port) + sock2 = serv.accept + serv.close + + 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() + ctx.ciphers = "ADH" + 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 + serv.close if serv && !serv.closed? + sock1.close if sock1 && !sock1.closed? + sock2.close if sock2 && !sock2.closed? + end + end end |