Skip to content

Commit 2048aee

Browse files
wip
1 parent 62fd3e4 commit 2048aee

File tree

4 files changed

+218
-11
lines changed

4 files changed

+218
-11
lines changed

ext/openssl/ossl_bio.c

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,108 @@ ossl_membio2str(BIO *bio)
4040

4141
return ret;
4242
}
43+
44+
int
45+
ossl_membio_sock_read(BIO* bio, VALUE io) {
46+
VALUE nonblock_kwargs = rb_hash_new();
47+
rb_hash_aset(nonblock_kwargs, ID2SYM(rb_intern("exception")), Qfalse);
48+
49+
printf("reading...\n");
50+
51+
VALUE fargs[] = { INT2NUM(4096), nonblock_kwargs };
52+
VALUE ret = rb_funcallv_public_kw(io, rb_intern("read_nonblock"), 2, fargs, RB_PASS_KEYWORDS);
53+
printf("just read...\n");
54+
int len;
55+
char *bstr;
56+
57+
if (RB_TYPE_P(ret, T_STRING)) {
58+
len = RSTRING_LENINT(ret);
59+
bstr = RSTRING_PTR(ret);
60+
printf("read the nonblock: %d...\n", len);
61+
}
62+
else if (ret == ID2SYM(rb_intern("wait_readable"))) {
63+
// BIO_set_retry_read(bio);
64+
return SSL_ERROR_WANT_READ;
65+
}
66+
else if (ret == ID2SYM(rb_intern("wait_writable"))) {
67+
// BIO_set_retry_write(bio);
68+
return SSL_ERROR_WANT_WRITE;
69+
}
70+
else if (NIL_P(ret)) {
71+
printf("fuck the nil\n");
72+
return SSL_ERROR_ZERO_RETURN;
73+
}
74+
else {
75+
printf("elsing\n");
76+
rb_raise(rb_eTypeError, "write_nonblock must return an Integer, "
77+
":wait_readable, or :wait_writable");
78+
}
79+
80+
while (len > 0) {
81+
int n = BIO_write(bio, bstr, len);
82+
BIO_clear_retry_flags(bio);
83+
84+
if (n<=0)
85+
return SSL_ERROR_SYSCALL; // unrecoverable
86+
87+
bstr += n;
88+
len -= n;
89+
90+
// // finish handshake if required
91+
// if (!SSL_is_init_finished(client.ssl)) {
92+
// if (do_ssl_handshake() == SSLSTATUS_FAIL)
93+
// return SSL_ERROR_SYSCALL;
94+
// if (!SSL_is_init_finished(client.ssl))
95+
// // assume there are bytes missing
96+
// return SSL_ERROR_WANT_READ;
97+
// }
98+
}
99+
return SSL_ERROR_NONE;
100+
}
101+
102+
int
103+
ossl_membio_sock_write(BIO* bio, VALUE io) {
104+
char buf[4096];
105+
char *p = buf;
106+
107+
int n = BIO_read(bio, p, 4096);
108+
BIO_clear_retry_flags(bio);
109+
if (n <= 0) {
110+
if (!BIO_should_retry(bio))
111+
// TODO: raise exception
112+
return -1;
113+
}
114+
115+
printf("writing to bio 2: %d\n", n);
116+
117+
VALUE nonblock_kwargs = rb_hash_new();
118+
rb_hash_aset(nonblock_kwargs, ID2SYM(rb_intern("exception")), Qfalse);
119+
120+
VALUE fargs[] = { rb_str_new_static(buf, n), nonblock_kwargs };
121+
122+
// rb_io_write(rb_stdout ,rb_sprintf("%s\n", RSTRING_PTR(*biobuf)));
123+
// rb_p(*biobuf);
124+
VALUE ret = rb_funcallv_public_kw(io, rb_intern("write_nonblock"), 2, fargs, RB_PASS_KEYWORDS);
125+
126+
if (RB_INTEGER_TYPE_P(ret)) {
127+
// TODO: resize buffer
128+
return SSL_ERROR_NONE;
129+
}
130+
else if (ret == ID2SYM(rb_intern("wait_readable"))) {
131+
printf("wred\n");
132+
// BIO_set_retry_read(bio);
133+
return SSL_ERROR_WANT_READ;
134+
}
135+
else if (ret == ID2SYM(rb_intern("wait_writable"))) {
136+
printf("wwrit\n");
137+
// BIO_set_retry_write(bio);
138+
return SSL_ERROR_WANT_WRITE;
139+
} else if (NIL_P(ret)) {
140+
printf("closed\n");
141+
return SSL_ERROR_ZERO_RETURN;
142+
}
143+
else {
144+
rb_raise(rb_eTypeError, "write_nonblock must return an Integer, "
145+
":wait_readable, or :wait_writable");
146+
}
147+
}

ext/openssl/ossl_bio.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,7 @@
1212

1313
BIO *ossl_obj2bio(volatile VALUE *);
1414
VALUE ossl_membio2str(BIO*);
15+
int ossl_membio_sock_read(BIO *, VALUE);
16+
int ossl_membio_sock_write(BIO * , VALUE);
1517

1618
#endif

ext/openssl/ossl_ssl.c

Lines changed: 110 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,15 @@ static ID id_i_io, id_i_context, id_i_hostname;
5757

5858
static int ossl_ssl_ex_vcb_idx;
5959
static int ossl_ssl_ex_ptr_idx;
60+
static int ossl_ssl_ex_rbio_idx;
61+
static int ossl_ssl_ex_wbio_idx;
6062
static int ossl_sslctx_ex_ptr_idx;
6163

64+
65+
int IsSock(VALUE io) {
66+
return RB_TYPE_P(io, T_FILE);
67+
}
68+
6269
static void
6370
ossl_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

ext/openssl/ossl_ssl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ extern const rb_data_type_t ossl_ssl_session_type;
2929
extern VALUE mSSL;
3030
extern VALUE cSSLSocket;
3131
extern VALUE cSSLSession;
32+
static VALUE nonblock_kwargs;
3233

3334
void Init_ossl_ssl(void);
3435
void Init_ossl_ssl_session(void);

0 commit comments

Comments
 (0)