Tony Arcieri
2/8/2008 1:35:00 AM
[Note: parts of this message were removed to make it a legal post.]
On Feb 7, 2008 1:48 PM, MenTaLguY <mental@rydia.net> wrote:
> On Fri, 8 Feb 2008 05:38:57 +0900, "Tony Arcieri" <tony@clickcaster.com>
> wrote:
> > Has there been any consideration as to adding something like
> > OpenSSL::SSL::SSLSocket#connect_nonblock and #accept_nonblock to go
> along
> > with Socket#connect_nonblock and Socket#accept_nonblock?
>
> I would favor this solution myself.
>
> -mental
>
Well, I managed to create a subclass of OpenSSL::SSL::SSLSocket in a C
extension which implements #connect_nonblock and #accept_nonblock. It was
quite a hack: #connect and #accept both call the static C function
ossl_ssl_setup(), which for whatever reason is not called from #initialize.
I managed to do it by finding a third method, #session=, which also calls
ossl_ssl_setup(). I couldn't really figure out what this is for... there's
a whole OpenSSL::SSL::Session class defined in ossl_ssl_session.c, but the
Init function for this file is never called, so while it's linked into the
OpenSSL C extension, it's not accessible in the Ruby environment.
I fed #session= a bogus parameter (nil), and fortunately the method calls
ossl_ssl_setup() before doing any typechecking on its arguments. This meant
I could catch the exception it threw due to the bogus argument, but
ossl_ssl_setup() was still called.
Changing the ossl_start_ssl() function that #connect and #accept call into a
non-blocking one was pretty trivial: I just had it raise exceptions for when
it needed more data to complete the connection, rather than calling
rb_io_wait_readable() / rb_io_wait_writable(). If there's any interest I
can contribute the code back to the OpenSSL extension, but since it's so
trivial I'd encourage someone on the OpenSSL team to implement it
themselves.
--
Tony Arcieri
ClickCaster, Inc.
tony@clickcaster.com