diff options
Diffstat (limited to 'ext/openssl/ossl_ssl.c')
-rw-r--r-- | ext/openssl/ossl_ssl.c | 62 |
1 files changed, 41 insertions, 21 deletions
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index af93252e..1a67d35d 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -107,7 +107,7 @@ static const char *ossl_ssl_attrs[] = { ID ID_callback_state; -static VALUE sym_exception; +static VALUE sym_exception, sym_wait_readable, sym_wait_writable; /* * SSLContext class @@ -1271,7 +1271,8 @@ read_would_block(int nonblock) } static VALUE -ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, int nonblock) +ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, + int nonblock, int no_exception) { SSL *ssl; rb_io_t *fptr; @@ -1295,10 +1296,12 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, int nonblock) switch((ret2 = ssl_get_error(ssl, ret))){ case SSL_ERROR_WANT_WRITE: + if (no_exception) { return sym_wait_writable; } write_would_block(nonblock); rb_io_wait_writable(FPTR_TO_FD(fptr)); continue; case SSL_ERROR_WANT_READ: + if (no_exception) { return sym_wait_readable; } read_would_block(nonblock); rb_io_wait_readable(FPTR_TO_FD(fptr)); continue; @@ -1324,7 +1327,7 @@ static VALUE ossl_ssl_connect(VALUE self) { ossl_ssl_setup(self); - return ossl_start_ssl(self, SSL_connect, "SSL_connect", 0); + return ossl_start_ssl(self, SSL_connect, "SSL_connect", 0, 0); } /* @@ -1349,7 +1352,7 @@ static VALUE ossl_ssl_connect_nonblock(VALUE self) { ossl_ssl_setup(self); - return ossl_start_ssl(self, SSL_connect, "SSL_connect", 1); + return ossl_start_ssl(self, SSL_connect, "SSL_connect", 1, 0); } /* @@ -1363,12 +1366,20 @@ static VALUE ossl_ssl_accept(VALUE self) { ossl_ssl_setup(self); - return ossl_start_ssl(self, SSL_accept, "SSL_accept", 0); + return ossl_start_ssl(self, SSL_accept, "SSL_accept", 0, 0); +} + +static int +get_no_exception(VALUE opts) +{ + if (!NIL_P(opts) && Qfalse == rb_hash_lookup2(opts, sym_exception, Qundef)) + return 1; + return 0; } /* * call-seq: - * ssl.accept_nonblock => self + * ssl.accept_nonblock([options]) => self * * Initiates the SSL/TLS handshake as a server in non-blocking manner. * @@ -1383,12 +1394,22 @@ ossl_ssl_accept(VALUE self) * retry * end * + * By specifying `exception: false`, the options hash allows you to indicate + * that accept_nonblock should not raise an IO::WaitReadable or + * IO::WaitWritable exception, but return the symbol :wait_readable or + * :wait_writable instead. */ static VALUE -ossl_ssl_accept_nonblock(VALUE self) +ossl_ssl_accept_nonblock(int argc, VALUE *argv, VALUE self) { + int no_exception; + VALUE opts = Qnil; + + rb_scan_args(argc, argv, "0:", &opts); + no_exception = get_no_exception(opts); + ossl_ssl_setup(self); - return ossl_start_ssl(self, SSL_accept, "SSL_accept", 1); + return ossl_start_ssl(self, SSL_accept, "SSL_accept", 1, no_exception); } static VALUE @@ -1396,15 +1417,13 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) { SSL *ssl; int ilen, nread = 0; - int no_exception = 0; + int no_exception; VALUE len, str; rb_io_t *fptr; VALUE opts = Qnil; rb_scan_args(argc, argv, "11:", &len, &str, &opts); - - if (!NIL_P(opts) && Qfalse == rb_hash_aref(opts, sym_exception)) - no_exception = 1; + no_exception = get_no_exception(opts); ilen = NUM2INT(len); if(NIL_P(str)) str = rb_str_new(0, ilen); @@ -1429,12 +1448,12 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) if (no_exception) { return Qnil; } rb_eof_error(); case SSL_ERROR_WANT_WRITE: - if (no_exception) { return ID2SYM(rb_intern("wait_writable")); } + if (no_exception) { return sym_wait_writable; } write_would_block(nonblock); rb_io_wait_writable(FPTR_TO_FD(fptr)); continue; case SSL_ERROR_WANT_READ: - if (no_exception) { return ID2SYM(rb_intern("wait_readable")); } + if (no_exception) { return sym_wait_readable; } read_would_block(nonblock); rb_io_wait_readable(FPTR_TO_FD(fptr)); continue; @@ -1517,12 +1536,12 @@ ossl_ssl_write_internal(VALUE self, VALUE str, int nonblock, int no_exception) case SSL_ERROR_NONE: goto end; case SSL_ERROR_WANT_WRITE: - if (no_exception) { return ID2SYM(rb_intern("wait_writable")); } + if (no_exception) { return sym_wait_writable; } write_would_block(nonblock); rb_io_wait_writable(FPTR_TO_FD(fptr)); continue; case SSL_ERROR_WANT_READ: - if (no_exception) { return ID2SYM(rb_intern("wait_readable")); } + if (no_exception) { return sym_wait_readable; } read_would_block(nonblock); rb_io_wait_readable(FPTR_TO_FD(fptr)); continue; @@ -1567,12 +1586,10 @@ ossl_ssl_write_nonblock(int argc, VALUE *argv, VALUE self) { VALUE str; VALUE opts = Qnil; - int no_exception = 0; + int no_exception; rb_scan_args(argc, argv, "1:", &str, &opts); - - if (!NIL_P(opts) && Qfalse == rb_hash_aref(opts, sym_exception)) - no_exception = 1; + no_exception = get_no_exception(opts); return ossl_ssl_write_internal(self, str, 1, no_exception); } @@ -2220,7 +2237,7 @@ Init_ossl_ssl(void) 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, "accept_nonblock", ossl_ssl_accept_nonblock, -1); 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); @@ -2298,5 +2315,8 @@ Init_ossl_ssl(void) ossl_ssl_def_const(OP_NETSCAPE_CA_DN_BUG); ossl_ssl_def_const(OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG); +#undef rb_intern sym_exception = ID2SYM(rb_intern("exception")); + sym_wait_readable = ID2SYM(rb_intern("wait_readable")); + sym_wait_writable = ID2SYM(rb_intern("wait_writable")); } |