* 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
This commit is contained in:
parent
f65d706529
commit
7fd155cf0f
13
ChangeLog
13
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>
|
Sat Mar 21 08:19:52 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* process.c (rb_exec): prints error message only on platforms
|
* process.c (rb_exec): prints error message only on platforms
|
||||||
|
5
NEWS
5
NEWS
@ -37,6 +37,7 @@ with all sufficient information, see the ChangeLog file.
|
|||||||
* new modules:
|
* new modules:
|
||||||
* IO::WaitReadable
|
* IO::WaitReadable
|
||||||
* IO::WaitWritable
|
* IO::WaitWritable
|
||||||
|
They are used to extend non-blocking exceptions.
|
||||||
|
|
||||||
* Process
|
* Process
|
||||||
* extended methods:
|
* extended methods:
|
||||||
@ -91,9 +92,11 @@ with all sufficient information, see the ChangeLog file.
|
|||||||
* PTY.open
|
* PTY.open
|
||||||
|
|
||||||
* openssl
|
* openssl
|
||||||
* new method:
|
* new methods:
|
||||||
* OpenSSL::Buffering#read_nonblock
|
* OpenSSL::Buffering#read_nonblock
|
||||||
* OpenSSL::Buffering#write_nonblock
|
* OpenSSL::Buffering#write_nonblock
|
||||||
|
* OpenSSL::SSL::SSLSocket#connect_nonblock
|
||||||
|
* OpenSSL::SSL::SSLSocket#accept_nonblock
|
||||||
|
|
||||||
* socket
|
* socket
|
||||||
|
|
||||||
|
@ -1020,8 +1020,28 @@ ossl_ssl_setup(VALUE self)
|
|||||||
#define ssl_get_error(ssl, ret) SSL_get_error(ssl, ret)
|
#define ssl_get_error(ssl, ret) SSL_get_error(ssl, ret)
|
||||||
#endif
|
#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
|
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;
|
SSL *ssl;
|
||||||
rb_io_t *fptr;
|
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))){
|
switch((ret2 = ssl_get_error(ssl, ret))){
|
||||||
case SSL_ERROR_WANT_WRITE:
|
case SSL_ERROR_WANT_WRITE:
|
||||||
|
write_would_block(nonblock);
|
||||||
rb_io_wait_writable(FPTR_TO_FD(fptr));
|
rb_io_wait_writable(FPTR_TO_FD(fptr));
|
||||||
continue;
|
continue;
|
||||||
case SSL_ERROR_WANT_READ:
|
case SSL_ERROR_WANT_READ:
|
||||||
|
read_would_block(nonblock);
|
||||||
rb_io_wait_readable(FPTR_TO_FD(fptr));
|
rb_io_wait_readable(FPTR_TO_FD(fptr));
|
||||||
continue;
|
continue;
|
||||||
case SSL_ERROR_SYSCALL:
|
case SSL_ERROR_SYSCALL:
|
||||||
@ -1068,7 +1090,18 @@ static VALUE
|
|||||||
ossl_ssl_connect(VALUE self)
|
ossl_ssl_connect(VALUE self)
|
||||||
{
|
{
|
||||||
ossl_ssl_setup(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_accept(VALUE self)
|
||||||
{
|
{
|
||||||
ossl_ssl_setup(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
|
static VALUE
|
||||||
@ -1113,19 +1157,11 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
|
|||||||
case SSL_ERROR_ZERO_RETURN:
|
case SSL_ERROR_ZERO_RETURN:
|
||||||
rb_eof_error();
|
rb_eof_error();
|
||||||
case SSL_ERROR_WANT_WRITE:
|
case SSL_ERROR_WANT_WRITE:
|
||||||
if (nonblock) {
|
write_would_block(nonblock);
|
||||||
VALUE exc = ossl_exc_new(eSSLError, "write would block");
|
|
||||||
rb_extend_object(exc, rb_mWaitWritable);
|
|
||||||
rb_exc_raise(exc);
|
|
||||||
}
|
|
||||||
rb_io_wait_writable(FPTR_TO_FD(fptr));
|
rb_io_wait_writable(FPTR_TO_FD(fptr));
|
||||||
continue;
|
continue;
|
||||||
case SSL_ERROR_WANT_READ:
|
case SSL_ERROR_WANT_READ:
|
||||||
if (nonblock) {
|
read_would_block(nonblock);
|
||||||
VALUE exc = ossl_exc_new(eSSLError, "read would block");
|
|
||||||
rb_extend_object(exc, rb_mWaitReadable);
|
|
||||||
rb_exc_raise(exc);
|
|
||||||
}
|
|
||||||
rb_io_wait_readable(FPTR_TO_FD(fptr));
|
rb_io_wait_readable(FPTR_TO_FD(fptr));
|
||||||
continue;
|
continue;
|
||||||
case SSL_ERROR_SYSCALL:
|
case SSL_ERROR_SYSCALL:
|
||||||
@ -1198,19 +1234,11 @@ ossl_ssl_write_internal(VALUE self, VALUE str, int nonblock)
|
|||||||
case SSL_ERROR_NONE:
|
case SSL_ERROR_NONE:
|
||||||
goto end;
|
goto end;
|
||||||
case SSL_ERROR_WANT_WRITE:
|
case SSL_ERROR_WANT_WRITE:
|
||||||
if (nonblock) {
|
write_would_block(nonblock);
|
||||||
VALUE exc = ossl_exc_new(eSSLError, "write would block");
|
|
||||||
rb_extend_object(exc, rb_mWaitWritable);
|
|
||||||
rb_exc_raise(exc);
|
|
||||||
}
|
|
||||||
rb_io_wait_writable(FPTR_TO_FD(fptr));
|
rb_io_wait_writable(FPTR_TO_FD(fptr));
|
||||||
continue;
|
continue;
|
||||||
case SSL_ERROR_WANT_READ:
|
case SSL_ERROR_WANT_READ:
|
||||||
if (nonblock) {
|
read_would_block(nonblock);
|
||||||
VALUE exc = ossl_exc_new(eSSLError, "read would block");
|
|
||||||
rb_extend_object(exc, rb_mWaitReadable);
|
|
||||||
rb_exc_raise(exc);
|
|
||||||
}
|
|
||||||
rb_io_wait_readable(FPTR_TO_FD(fptr));
|
rb_io_wait_readable(FPTR_TO_FD(fptr));
|
||||||
continue;
|
continue;
|
||||||
case SSL_ERROR_SYSCALL:
|
case SSL_ERROR_SYSCALL:
|
||||||
@ -1566,7 +1594,9 @@ Init_ossl_ssl()
|
|||||||
rb_define_alias(cSSLSocket, "to_io", "io");
|
rb_define_alias(cSSLSocket, "to_io", "io");
|
||||||
rb_define_method(cSSLSocket, "initialize", ossl_ssl_initialize, -1);
|
rb_define_method(cSSLSocket, "initialize", ossl_ssl_initialize, -1);
|
||||||
rb_define_method(cSSLSocket, "connect", ossl_ssl_connect, 0);
|
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", 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_method(cSSLSocket, "sysread", ossl_ssl_read, -1);
|
||||||
rb_define_private_method(cSSLSocket, "sysread_nonblock", ossl_ssl_read_nonblock, -1);
|
rb_define_private_method(cSSLSocket, "sysread_nonblock", ossl_ssl_read_nonblock, -1);
|
||||||
rb_define_method(cSSLSocket, "syswrite", ossl_ssl_write, 1);
|
rb_define_method(cSSLSocket, "syswrite", ossl_ssl_write, 1);
|
||||||
|
@ -192,6 +192,62 @@ class OpenSSL::TestPair < Test::Unit::TestCase
|
|||||||
}
|
}
|
||||||
end
|
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
|
||||||
|
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user