summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-03-21 06:56:33 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-03-21 06:56:33 +0000
commit7fd155cf0f088f763dfb6353f251319775549b77 (patch)
tree7c0753f342b346115e93de4a40442b32b9879c9e
parentf65d706529969593b318e79ca26bf03c11b6347b (diff)
* 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--ChangeLog13
-rw-r--r--NEWS5
-rw-r--r--ext/openssl/ossl_ssl.c76
-rw-r--r--test/openssl/test_pair.rb56
4 files changed, 126 insertions, 24 deletions
diff --git a/ChangeLog b/ChangeLog
index 7d312ddb84..67184f7601 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/NEWS b/NEWS
index e250aa5d02..06eb4e7c3d 100644
--- a/NEWS
+++ b/NEWS
@@ -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