dumping ground for random patches and texts
 help / color / mirror / Atom feed
* [PATCH] openssl: avoid kwarg parsing from C API at startup
@ 2015-12-02  0:11 Eric Wong
  0 siblings, 0 replies; only message in thread
From: Eric Wong @ 2015-12-02  0:11 UTC (permalink / raw)
  To: spew

Benchmarks coming...
---
 ext/openssl/lib/openssl/ssl.rb |  48 ++++++++++++++++++++
 ext/openssl/ossl_ssl.c         | 101 ++++++++++++++---------------------------
 2 files changed, 81 insertions(+), 68 deletions(-)

diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb
index d3ae155..b273173 100644
--- a/ext/openssl/lib/openssl/ssl.rb
+++ b/ext/openssl/lib/openssl/ssl.rb
@@ -322,6 +322,54 @@ def session
         nil
       end
 
+      # call-seq:
+      #    ssl.accept_nonblock([options]) => self
+      #
+      # Initiates the SSL/TLS handshake as a server in non-blocking manner.
+      #
+      #   # emulates blocking accept
+      #   begin
+      #     ssl.accept_nonblock
+      #   rescue IO::WaitReadable
+      #     IO.select([s2])
+      #     retry
+      #   rescue IO::WaitWritable
+      #     IO.select(nil, [s2])
+      #     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.
+      def accept_nonblock(exception: true)
+        __accept_nonblock(exception)
+      end
+
+      # call-seq:
+      #    ssl.connect_nonblock([options]) => self
+      #
+      # Initiates the SSL/TLS handshake as a client in non-blocking manner.
+      #
+      #   # emulates blocking connect
+      #   begin
+      #     ssl.connect_nonblock
+      #   rescue IO::WaitReadable
+      #     IO.select([s2])
+      #     retry
+      #   rescue IO::WaitWritable
+      #     IO.select(nil, [s2])
+      #     retry
+      #   end
+      #
+      # By specifying `exception: false`, the options hash allows you to
+      # indicate that connect_nonblock should not raise an IO::WaitReadable or
+      # IO::WaitWritable exception, but return the symbol :wait_readable or
+      # :wait_writable instead.
+      def connect_nonblock(exception: true)
+        __connect_nonblock(exception)
+      end
+
       private
 
       def using_anon_cipher?
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index 553eb14..5018dcb 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -1271,14 +1271,19 @@ no_exception_p(VALUE opts)
     return 0;
 }
 
+/*
+ * nbex -
+ * * undef - blocking
+ * * true - non-blocking, raise exceptions on common errors
+ * * false - non-blocking, no exceptions on common errors
+ */
 static VALUE
-ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts)
+ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE nbex)
 {
     SSL *ssl;
     rb_io_t *fptr;
     int ret, ret2;
     VALUE cb_state;
-    int nonblock = opts != Qfalse;
 
     rb_ivar_set(self, ID_callback_state, Qnil);
 
@@ -1297,15 +1302,23 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts)
 
 	switch((ret2 = ssl_get_error(ssl, ret))){
 	case SSL_ERROR_WANT_WRITE:
-            if (no_exception_p(opts)) { return sym_wait_writable; }
-            write_would_block(nonblock);
-            rb_io_wait_writable(FPTR_TO_FD(fptr));
-            continue;
+	    switch (nbex) {
+	    case Qfalse: return sym_wait_writable;
+	    case Qundef:
+		rb_io_wait_writable(FPTR_TO_FD(fptr));
+		continue;
+	    default:
+		write_would_block(1);
+	    }
 	case SSL_ERROR_WANT_READ:
-            if (no_exception_p(opts)) { return sym_wait_readable; }
-            read_would_block(nonblock);
-            rb_io_wait_readable(FPTR_TO_FD(fptr));
-            continue;
+	    switch (nbex) {
+	    case Qfalse: return sym_wait_readable;
+	    case Qundef:
+		rb_io_wait_readable(FPTR_TO_FD(fptr));
+		continue;
+	    default:
+		read_would_block(1);
+	    }
 	case SSL_ERROR_SYSCALL:
 	    if (errno) rb_sys_fail(funcname);
 	    ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
@@ -1329,40 +1342,15 @@ ossl_ssl_connect(VALUE self)
 {
     ossl_ssl_setup(self);
 
-    return ossl_start_ssl(self, SSL_connect, "SSL_connect", Qfalse);
+    return ossl_start_ssl(self, SSL_connect, "SSL_connect", Qundef);
 }
 
-/*
- * call-seq:
- *    ssl.connect_nonblock([options]) => self
- *
- * Initiates the SSL/TLS handshake as a client in non-blocking manner.
- *
- *   # emulates blocking connect
- *   begin
- *     ssl.connect_nonblock
- *   rescue IO::WaitReadable
- *     IO.select([s2])
- *     retry
- *   rescue IO::WaitWritable
- *     IO.select(nil, [s2])
- *     retry
- *   end
- *
- * By specifying `exception: false`, the options hash allows you to indicate
- * that connect_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_connect_nonblock(int argc, VALUE *argv, VALUE self)
+ossl_ssl_connect_nonblock(VALUE self, VALUE ex)
 {
-    VALUE opts;
-    rb_scan_args(argc, argv, "0:", &opts);
-
     ossl_ssl_setup(self);
 
-    return ossl_start_ssl(self, SSL_connect, "SSL_connect", opts);
+    return ossl_start_ssl(self, SSL_connect, "SSL_connect", ex);
 }
 
 /*
@@ -1377,40 +1365,15 @@ ossl_ssl_accept(VALUE self)
 {
     ossl_ssl_setup(self);
 
-    return ossl_start_ssl(self, SSL_accept, "SSL_accept", Qfalse);
+    return ossl_start_ssl(self, SSL_accept, "SSL_accept", Qundef);
 }
 
-/*
- * call-seq:
- *    ssl.accept_nonblock([options]) => self
- *
- * Initiates the SSL/TLS handshake as a server in non-blocking manner.
- *
- *   # emulates blocking accept
- *   begin
- *     ssl.accept_nonblock
- *   rescue IO::WaitReadable
- *     IO.select([s2])
- *     retry
- *   rescue IO::WaitWritable
- *     IO.select(nil, [s2])
- *     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(int argc, VALUE *argv, VALUE self)
+ossl_ssl_accept_nonblock(VALUE self, VALUE ex)
 {
-    VALUE opts;
-
-    rb_scan_args(argc, argv, "0:", &opts);
     ossl_ssl_setup(self);
 
-    return ossl_start_ssl(self, SSL_accept, "SSL_accept", opts);
+    return ossl_start_ssl(self, SSL_accept, "SSL_accept", ex);
 }
 
 static VALUE
@@ -2287,9 +2250,11 @@ Init_ossl_ssl(void)
     rb_define_const(mSSLExtConfig, "OPENSSL_NO_SOCK", Qfalse);
     rb_define_alloc_func(cSSLSocket, ossl_ssl_s_alloc);
     rb_define_method(cSSLSocket, "connect",    ossl_ssl_connect, 0);
-    rb_define_method(cSSLSocket, "connect_nonblock",    ossl_ssl_connect_nonblock, -1);
+    rb_define_private_method(cSSLSocket, "__connect_nonblock",
+			     ossl_ssl_connect_nonblock, 1);
     rb_define_method(cSSLSocket, "accept",     ossl_ssl_accept, 0);
-    rb_define_method(cSSLSocket, "accept_nonblock", ossl_ssl_accept_nonblock, -1);
+    rb_define_private_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);
-- 
EW


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2015-12-02  0:11 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-02  0:11 [PATCH] openssl: avoid kwarg parsing from C API at startup Eric Wong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).