@@ -57,8 +57,15 @@ static ID id_i_io, id_i_context, id_i_hostname;
5757
5858static int ossl_ssl_ex_vcb_idx ;
5959static int ossl_ssl_ex_ptr_idx ;
60+ static int ossl_ssl_ex_rbio_idx ;
61+ static int ossl_ssl_ex_wbio_idx ;
6062static int ossl_sslctx_ex_ptr_idx ;
6163
64+
65+ int IsSock (VALUE io ) {
66+ return RB_TYPE_P (io , T_FILE );
67+ }
68+
6269static void
6370ossl_sslctx_mark (void * ptr )
6471{
@@ -1639,7 +1646,7 @@ ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
16391646
16401647 if (rb_respond_to (io , rb_intern ("nonblock=" )))
16411648 rb_funcall (io , rb_intern ("nonblock=" ), 1 , Qtrue );
1642- Check_Type (io , T_FILE );
1649+ // Check_Type(io, T_FILE);
16431650 rb_ivar_set (self , id_i_io , io );
16441651
16451652 ssl = SSL_new (ctx );
@@ -1682,11 +1689,22 @@ ossl_ssl_setup(VALUE self)
16821689 return Qtrue ;
16831690
16841691 io = rb_attr_get (self , id_i_io );
1685- GetOpenFile (io , fptr );
1686- rb_io_check_readable (fptr );
1687- rb_io_check_writable (fptr );
1688- if (!SSL_set_fd (ssl , TO_SOCKET (rb_io_descriptor (io ))))
1689- ossl_raise (eSSLError , "SSL_set_fd" );
1692+
1693+ if (IsSock (io )) {
1694+ GetOpenFile (io , fptr );
1695+ rb_io_check_readable (fptr );
1696+ rb_io_check_writable (fptr );
1697+ if (!SSL_set_fd (ssl , TO_SOCKET (rb_io_descriptor (io ))))
1698+ ossl_raise (eSSLError , "SSL_set_fd" );
1699+ } else {
1700+ // something which quacks like an IO
1701+ // TODO: how to best ensure this from the C API??
1702+ BIO * rbio = BIO_new (BIO_s_mem ());
1703+ BIO * wbio = BIO_new (BIO_s_mem ());
1704+ SSL_set_bio (ssl , rbio , wbio );
1705+ SSL_set_ex_data (ssl , ossl_ssl_ex_rbio_idx , (void * )rbio );
1706+ SSL_set_ex_data (ssl , ossl_ssl_ex_wbio_idx , (void * )wbio );
1707+ }
16901708
16911709 return Qtrue ;
16921710}
@@ -1789,6 +1807,15 @@ ossl_start_ssl(VALUE self, int (*func)(SSL *), const char *funcname, VALUE opts)
17891807 GetSSL (self , ssl );
17901808
17911809 VALUE io = rb_attr_get (self , id_i_io );
1810+
1811+ int is_sock = IsSock (io );
1812+ BIO * rbio , * wbio ;
1813+
1814+ if (!is_sock ) {
1815+ rbio = (BIO * )SSL_get_ex_data (ssl , ossl_ssl_ex_rbio_idx );
1816+ wbio = (BIO * )SSL_get_ex_data (ssl , ossl_ssl_ex_wbio_idx );
1817+ }
1818+
17921819 for (;;) {
17931820 ret = func (ssl );
17941821
@@ -1798,11 +1825,35 @@ ossl_start_ssl(VALUE self, int (*func)(SSL *), const char *funcname, VALUE opts)
17981825 ossl_clear_error ();
17991826 rb_jump_tag (NUM2INT (cb_state ));
18001827 }
1828+ printf ("connect ret: %d\n" , ret );
18011829
18021830 if (ret > 0 )
18031831 break ;
18041832
1805- switch ((ret2 = ssl_get_error (ssl , ret ))) {
1833+ ret2 = ssl_get_error (ssl , ret );
1834+ printf ("WANT_READ: %d, WANT_WRITE. %d\n" , SSL_ERROR_WANT_READ , SSL_ERROR_WANT_WRITE );
1835+ printf ("connect ret2: %d\n" , ret2 );
1836+
1837+ if (!is_sock ) {
1838+ if (ret2 == SSL_ERROR_WANT_WRITE ) {
1839+ ret2 = ossl_membio_sock_read (rbio , io );
1840+ if (ret2 == SSL_ERROR_NONE ) {
1841+ ret2 = SSL_ERROR_WANT_WRITE ;
1842+ printf ("out fuckerz\n" );
1843+ break ;
1844+ }
1845+ } else if (ret2 == SSL_ERROR_WANT_READ ) {
1846+ ret2 = ossl_membio_sock_write (wbio , io );
1847+ if (ret2 == SSL_ERROR_NONE ) {
1848+ printf ("out fuckerz\n" );
1849+ break ;
1850+ // continue;
1851+ }
1852+ }
1853+ }
1854+ printf ("connect after is_sock ret2: %d\n" , ret2 );
1855+
1856+ switch ((ret2 )) {
18061857 case SSL_ERROR_WANT_WRITE :
18071858 if (no_exception_p (opts )) { return sym_wait_writable ; }
18081859 write_would_block (nonblock );
@@ -1954,6 +2005,7 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
19542005 int ilen ;
19552006 VALUE len , str ;
19562007 VALUE opts = Qnil ;
2008+ BIO * rbio , * wbio ;
19572009
19582010 if (nonblock ) {
19592011 rb_scan_args (argc , argv , "11:" , & len , & str , & opts );
@@ -1979,11 +2031,28 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
19792031 return str ;
19802032
19812033 VALUE io = rb_attr_get (self , id_i_io );
2034+ int is_sock = IsSock (io );
2035+
2036+ if (!is_sock ) {
2037+ rbio = (BIO * )SSL_get_ex_data (ssl , ossl_ssl_ex_rbio_idx );
2038+ wbio = (BIO * )SSL_get_ex_data (ssl , ossl_ssl_ex_wbio_idx );
2039+ }
19822040
19832041 rb_str_locktmp (str );
19842042 for (;;) {
1985- int nread = ossl_ssl_read_impl (ssl , str , ilen );
1986- switch (ssl_get_error (ssl , nread )) {
2043+ int ret , nread ;
2044+
2045+ if (!is_sock ) {
2046+ ret = ossl_membio_sock_read (rbio , io );
2047+ if (ret == SSL_ERROR_NONE ) {
2048+ ret = ossl_membio_sock_write (wbio , io );
2049+ }
2050+ } else {
2051+ nread = ossl_ssl_read_impl (ssl , str , ilen );
2052+ ret = ssl_get_error (ssl , nread );
2053+ }
2054+
2055+ switch (ret ) {
19872056 case SSL_ERROR_NONE :
19882057 rb_str_unlocktmp (str );
19892058 rb_str_set_len (str , nread );
@@ -2080,16 +2149,35 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
20802149
20812150 tmp = rb_str_new_frozen (StringValue (str ));
20822151 VALUE io = rb_attr_get (self , id_i_io );
2083- GetOpenFile (io , fptr );
2152+ int is_sock = IsSock (io );
2153+ // BIO *rbio;
2154+ BIO * wbio ;
2155+
2156+ if (!is_sock ) {
2157+ // rbio = (BIO *)SSL_get_ex_data(ssl, ossl_ssl_ex_rbio_idx);
2158+ wbio = (BIO * )SSL_get_ex_data (ssl , ossl_ssl_ex_wbio_idx );
2159+ } else {
2160+ GetOpenFile (io , fptr );
2161+ }
20842162
20852163 /* SSL_write(3ssl) manpage states num == 0 is undefined */
20862164 num = RSTRING_LENINT (tmp );
20872165 if (num == 0 )
20882166 return INT2FIX (0 );
20892167
20902168 for (;;) {
2169+
2170+
20912171 int nwritten = ossl_ssl_write_impl (ssl , tmp , num );
2092- switch (ssl_get_error (ssl , nwritten )) {
2172+ int ret = ssl_get_error (ssl , nwritten );
2173+
2174+ if (!is_sock ) {
2175+ if (ret == SSL_ERROR_NONE ) {
2176+ ret = ossl_membio_sock_write (wbio , io );
2177+ }
2178+ }
2179+
2180+ switch (ret ) {
20932181 case SSL_ERROR_NONE :
20942182 return INT2NUM (nwritten );
20952183 case SSL_ERROR_WANT_WRITE :
@@ -2623,6 +2711,12 @@ Init_ossl_ssl(void)
26232711 ossl_ssl_ex_ptr_idx = SSL_get_ex_new_index (0 , (void * )"ossl_ssl_ex_ptr_idx" , 0 , 0 , 0 );
26242712 if (ossl_ssl_ex_ptr_idx < 0 )
26252713 ossl_raise (rb_eRuntimeError , "SSL_get_ex_new_index" );
2714+ ossl_ssl_ex_rbio_idx = SSL_get_ex_new_index (0 , (void * )"ossl_ssl_ex_rbio_idx" , 0 , 0 , 0 );
2715+ if (ossl_ssl_ex_rbio_idx < 0 )
2716+ ossl_raise (rb_eRuntimeError , "SSL_get_ex_new_index" );
2717+ ossl_ssl_ex_wbio_idx = SSL_get_ex_new_index (0 , (void * )"ossl_ssl_ex_wbio_idx" , 0 , 0 , 0 );
2718+ if (ossl_ssl_ex_wbio_idx < 0 )
2719+ ossl_raise (rb_eRuntimeError , "SSL_get_ex_new_index" );
26262720 ossl_sslctx_ex_ptr_idx = SSL_CTX_get_ex_new_index (0 , (void * )"ossl_sslctx_ex_ptr_idx" , 0 , 0 , 0 );
26272721 if (ossl_sslctx_ex_ptr_idx < 0 )
26282722 ossl_raise (rb_eRuntimeError , "SSL_CTX_get_ex_new_index" );
@@ -3152,6 +3246,11 @@ Init_ossl_ssl(void)
31523246 id_npn_protocols_encoded = rb_intern_const ("npn_protocols_encoded" );
31533247 id_each = rb_intern_const ("each" );
31543248
3249+ nonblock_kwargs = rb_hash_new ();
3250+ rb_hash_aset (nonblock_kwargs , sym_exception , Qfalse );
3251+ rb_obj_freeze (nonblock_kwargs );
3252+ rb_global_variable (& nonblock_kwargs );
3253+
31553254#define DefIVarID (name ) do \
31563255 id_i_##name = rb_intern_const("@"#name); while (0)
31573256
0 commit comments