@@ -57,8 +57,15 @@ static ID id_i_io, id_i_context, id_i_hostname;
57
57
58
58
static int ossl_ssl_ex_vcb_idx ;
59
59
static int ossl_ssl_ex_ptr_idx ;
60
+ static int ossl_ssl_ex_rbio_idx ;
61
+ static int ossl_ssl_ex_wbio_idx ;
60
62
static int ossl_sslctx_ex_ptr_idx ;
61
63
64
+
65
+ int IsSock (VALUE io ) {
66
+ return RB_TYPE_P (io , T_FILE );
67
+ }
68
+
62
69
static void
63
70
ossl_sslctx_mark (void * ptr )
64
71
{
@@ -1639,7 +1646,7 @@ ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
1639
1646
1640
1647
if (rb_respond_to (io , rb_intern ("nonblock=" )))
1641
1648
rb_funcall (io , rb_intern ("nonblock=" ), 1 , Qtrue );
1642
- Check_Type (io , T_FILE );
1649
+ // Check_Type(io, T_FILE);
1643
1650
rb_ivar_set (self , id_i_io , io );
1644
1651
1645
1652
ssl = SSL_new (ctx );
@@ -1682,11 +1689,22 @@ ossl_ssl_setup(VALUE self)
1682
1689
return Qtrue ;
1683
1690
1684
1691
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
+ }
1690
1708
1691
1709
return Qtrue ;
1692
1710
}
@@ -1789,6 +1807,15 @@ ossl_start_ssl(VALUE self, int (*func)(SSL *), const char *funcname, VALUE opts)
1789
1807
GetSSL (self , ssl );
1790
1808
1791
1809
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
+
1792
1819
for (;;) {
1793
1820
ret = func (ssl );
1794
1821
@@ -1798,11 +1825,35 @@ ossl_start_ssl(VALUE self, int (*func)(SSL *), const char *funcname, VALUE opts)
1798
1825
ossl_clear_error ();
1799
1826
rb_jump_tag (NUM2INT (cb_state ));
1800
1827
}
1828
+ printf ("connect ret: %d\n" , ret );
1801
1829
1802
1830
if (ret > 0 )
1803
1831
break ;
1804
1832
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 )) {
1806
1857
case SSL_ERROR_WANT_WRITE :
1807
1858
if (no_exception_p (opts )) { return sym_wait_writable ; }
1808
1859
write_would_block (nonblock );
@@ -1954,6 +2005,7 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
1954
2005
int ilen ;
1955
2006
VALUE len , str ;
1956
2007
VALUE opts = Qnil ;
2008
+ BIO * rbio , * wbio ;
1957
2009
1958
2010
if (nonblock ) {
1959
2011
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)
1979
2031
return str ;
1980
2032
1981
2033
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
+ }
1982
2040
1983
2041
rb_str_locktmp (str );
1984
2042
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 ) {
1987
2056
case SSL_ERROR_NONE :
1988
2057
rb_str_unlocktmp (str );
1989
2058
rb_str_set_len (str , nread );
@@ -2080,16 +2149,35 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
2080
2149
2081
2150
tmp = rb_str_new_frozen (StringValue (str ));
2082
2151
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
+ }
2084
2162
2085
2163
/* SSL_write(3ssl) manpage states num == 0 is undefined */
2086
2164
num = RSTRING_LENINT (tmp );
2087
2165
if (num == 0 )
2088
2166
return INT2FIX (0 );
2089
2167
2090
2168
for (;;) {
2169
+
2170
+
2091
2171
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 ) {
2093
2181
case SSL_ERROR_NONE :
2094
2182
return INT2NUM (nwritten );
2095
2183
case SSL_ERROR_WANT_WRITE :
@@ -2623,6 +2711,12 @@ Init_ossl_ssl(void)
2623
2711
ossl_ssl_ex_ptr_idx = SSL_get_ex_new_index (0 , (void * )"ossl_ssl_ex_ptr_idx" , 0 , 0 , 0 );
2624
2712
if (ossl_ssl_ex_ptr_idx < 0 )
2625
2713
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" );
2626
2720
ossl_sslctx_ex_ptr_idx = SSL_CTX_get_ex_new_index (0 , (void * )"ossl_sslctx_ex_ptr_idx" , 0 , 0 , 0 );
2627
2721
if (ossl_sslctx_ex_ptr_idx < 0 )
2628
2722
ossl_raise (rb_eRuntimeError , "SSL_CTX_get_ex_new_index" );
@@ -3152,6 +3246,11 @@ Init_ossl_ssl(void)
3152
3246
id_npn_protocols_encoded = rb_intern_const ("npn_protocols_encoded" );
3153
3247
id_each = rb_intern_const ("each" );
3154
3248
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
+
3155
3254
#define DefIVarID (name ) do \
3156
3255
id_i_##name = rb_intern_const("@"#name); while (0)
3157
3256
0 commit comments