Index: ext/openssl/ossl_ssl.c =================================================================== --- ext/openssl/ossl_ssl.c (revision 20459) +++ ext/openssl/ossl_ssl.c (working copy) @@ -12,6 +12,14 @@ */ #include "ossl.h" +#define rb_sys_fail_path(path) rb_sys_fail(NIL_P(path) ? 0 : RSTRING_PTR(path)) + +#if defined(HAVE_FCNTL_H) || defined(_WIN32) +#include +#elif defined(HAVE_SYS_FCNTL_H) +#include +#endif + #if defined(HAVE_UNISTD_H) # include /* for read(), and write() */ #endif @@ -1034,7 +1042,11 @@ rb_io_wait_writable(FPTR_TO_FD(fptr)); continue; case SSL_ERROR_WANT_READ: - rb_io_wait_readable(FPTR_TO_FD(fptr)); + if (fcntl(fptr->fd, F_GETFL, O_NONBLOCK) == 1) { + rb_sys_fail_path(fptr->pathv); + } else { + rb_io_wait_readable(FPTR_TO_FD(fptr)); + } continue; case SSL_ERROR_SYSCALL: if(ERR_peek_error() == 0 && nread == 0) rb_eof_error(); @@ -1059,6 +1071,27 @@ /* * call-seq: + * ssl.read_nonblock(length) => string + * ssl.read_nonblock(length, buffer) => buffer + * + * === Parameters + * * +length+ is a positive integer. + * * +buffer+ is a string used to store the result. + */ +static VALUE +ossl_ssl_read_nonblock(int argc, VALUE *argv, VALUE self) +{ + SSL *ssl; + rb_io_t *fptr; + + Data_Get_Struct(self, SSL, ssl); + GetOpenFile(ossl_ssl_get_io(self), fptr); + rb_io_set_nonblock(fptr); + return ossl_ssl_read(argc, argv, self); +} + +/* + * call-seq: * ssl.syswrite(string) => integer */ static VALUE @@ -1421,6 +1454,7 @@ rb_define_method(cSSLSocket, "sysread", ossl_ssl_read, -1); rb_define_method(cSSLSocket, "syswrite", ossl_ssl_write, 1); rb_define_method(cSSLSocket, "sysclose", ossl_ssl_close, 0); + rb_define_method(cSSLSocket, "read_nonblock", ossl_ssl_read_nonblock, -1); rb_define_method(cSSLSocket, "cert", ossl_ssl_get_cert, 0); rb_define_method(cSSLSocket, "peer_cert", ossl_ssl_get_peer_cert, 0); rb_define_method(cSSLSocket, "peer_cert_chain", ossl_ssl_get_peer_cert_chain, 0);