88 * (See the file 'LICENCE'.)
99 */
1010#include "ossl.h"
11+ #include <openssl/bio.h>
1112
1213BIO *
1314ossl_obj2bio(volatile VALUE *pobj)
@@ -42,7 +43,8 @@ ossl_membio2str(BIO *bio)
4243}
4344
4445BIO_METHOD *ossl_bio_meth;
45- static int bio_state_idx, bio_errinfo_idx;
46+ static int bio_state_idx, bio_errinfo_idx, bio_eof_idx;
47+ static VALUE nonblock_kwargs;
4648
4749static void
4850bio_save_error(BIO *bio, int state)
@@ -77,8 +79,8 @@ ossl_bio_restore_error(BIO *bio)
7779struct bwrite_args {
7880 BIO *bio;
7981 const char *data;
80- size_t dlen;
81- size_t * written;
82+ int dlen;
83+ int written;
8284};
8385
8486static VALUE
@@ -88,15 +90,12 @@ bio_bwrite0(VALUE args)
8890 VALUE io = (VALUE)BIO_get_data(p->bio);
8991 BIO_clear_retry_flags(p->bio);
9092
91- VALUE str = rb_str_new_static(p->data, p->dlen);
92- VALUE kwargs = rb_hash_new();
93- rb_hash_aset(kwargs, ID2SYM(rb_intern("exception")), Qfalse);
94- VALUE funcallargs[] = { str, kwargs };
93+ VALUE fargs[] = { rb_str_new_static(p->data, p->dlen), nonblock_kwargs };
9594 VALUE ret = rb_funcallv_public_kw(io, rb_intern("write_nonblock"),
96- 2, funcallargs , RB_PASS_KEYWORDS);
95+ 2, fargs , RB_PASS_KEYWORDS);
9796
9897 if (RB_INTEGER_TYPE_P(ret)) {
99- * p->written = NUM2SIZET (ret);
98+ p->written = NUM2INT (ret);
10099 return INT2FIX(1);
101100 }
102101 else if (ret == ID2SYM(rb_intern("wait_readable"))) {
@@ -114,23 +113,25 @@ bio_bwrite0(VALUE args)
114113}
115114
116115static int
117- bio_bwrite(BIO *bio, const char *data, size_t dlen, size_t *written )
116+ bio_bwrite(BIO *bio, const char *data, int dlen)
118117{
119- struct bwrite_args args = { bio, data, dlen, written };
118+ struct bwrite_args args = { bio, data, dlen, 0 };
120119 int state;
121120
122121 VALUE ret = rb_protect(bio_bwrite0, (VALUE)&args, &state);
123122 bio_save_error(bio, state);
124123 if (state)
125124 return 0;
126- return FIX2INT(ret);
125+ if (FIX2INT(ret))
126+ return args.written;
127+ return -1;
127128}
128129
129130struct bread_args {
130131 BIO *bio;
131132 char *data;
132- size_t dlen;
133- size_t * readbytes;
133+ int dlen;
134+ int readbytes;
134135};
135136
136137static VALUE
@@ -140,22 +141,21 @@ bio_bread0(VALUE args)
140141 VALUE io = (VALUE)BIO_get_data(p->bio);
141142 BIO_clear_retry_flags(p->bio);
142143
143- VALUE kwargs = rb_hash_new();
144- rb_hash_aset(kwargs, ID2SYM(rb_intern("exception")), Qfalse);
145- VALUE funcallargs[] = { SIZET2NUM(p->dlen), kwargs };
144+ VALUE fargs[] = { INT2NUM(p->dlen), nonblock_kwargs };
146145 VALUE ret = rb_funcallv_public_kw(io, rb_intern("read_nonblock"),
147- 2, funcallargs , RB_PASS_KEYWORDS);
146+ 2, fargs , RB_PASS_KEYWORDS);
148147
149148 if (RB_TYPE_P(ret, T_STRING)) {
150- size_t len = (size_t)RSTRING_LEN (ret);
149+ int len = RSTRING_LENINT (ret);
151150 if (len > p->dlen)
152151 rb_raise(rb_eTypeError, "read_nonblock returned too much data");
153152 memcpy(p->data, RSTRING_PTR(ret), len);
154- * p->readbytes = len;
153+ p->readbytes = len;
155154 return INT2FIX(1);
156155 }
157156 else if (NIL_P(ret)) {
158- BIO_set_flags(p->bio, BIO_FLAGS_IN_EOF);
157+ // In OpenSSL 3.0 or later: BIO_set_flags(p->bio, BIO_FLAGS_IN_EOF);
158+ BIO_set_ex_data(p->bio, bio_eof_idx, (void *)1);
159159 return INT2FIX(0);
160160 }
161161 else if (ret == ID2SYM(rb_intern("wait_readable"))) {
@@ -173,16 +173,18 @@ bio_bread0(VALUE args)
173173}
174174
175175static int
176- bio_bread(BIO *bio, char *data, size_t dlen, size_t *readbytes )
176+ bio_bread(BIO *bio, char *data, int dlen)
177177{
178- struct bread_args args = { bio, data, dlen, readbytes };
178+ struct bread_args args = { bio, data, dlen, 0 };
179179 int state;
180180
181181 VALUE ret = rb_protect(bio_bread0, (VALUE)&args, &state);
182182 bio_save_error(bio, state);
183183 if (state)
184184 return 0;
185- return FIX2INT(ret);
185+ if (FIX2INT(ret))
186+ return args.readbytes;
187+ return -1;
186188}
187189
188190static VALUE
@@ -199,7 +201,7 @@ bio_ctrl(BIO *bio, int cmd, long larg, void *parg)
199201
200202 switch (cmd) {
201203 case BIO_CTRL_EOF:
202- return BIO_test_flags( bio, BIO_FLAGS_IN_EOF );
204+ return (int)(uintptr_t)BIO_get_ex_data( bio, bio_eof_idx );
203205 case BIO_CTRL_FLUSH:
204206 rb_protect(bio_flush0, (VALUE)bio, &state);
205207 bio_save_error(bio, state);
@@ -213,17 +215,22 @@ void
213215Init_ossl_bio(void)
214216{
215217 if ((bio_state_idx = BIO_get_ex_new_index(0, NULL, NULL, NULL, NULL)) < 0 ||
216- (bio_errinfo_idx = BIO_get_ex_new_index(0, NULL, NULL, NULL, NULL)) < 0)
218+ (bio_errinfo_idx = BIO_get_ex_new_index(0, NULL, NULL, NULL, NULL)) < 0 ||
219+ (bio_eof_idx = BIO_get_ex_new_index(0, NULL, NULL, NULL, NULL)) < 0)
217220 ossl_raise(eOSSLError, "BIO_get_ex_new_index");
218221
219222 ossl_bio_meth = BIO_meth_new(BIO_TYPE_SOURCE_SINK, "Ruby IO-like object");
220223 if (!ossl_bio_meth)
221224 ossl_raise(eOSSLError, "BIO_meth_new");
222- if (!BIO_meth_set_write_ex (ossl_bio_meth, bio_bwrite) ||
223- !BIO_meth_set_read_ex (ossl_bio_meth, bio_bread) ||
225+ if (!BIO_meth_set_write (ossl_bio_meth, bio_bwrite) ||
226+ !BIO_meth_set_read (ossl_bio_meth, bio_bread) ||
224227 !BIO_meth_set_ctrl(ossl_bio_meth, bio_ctrl)) {
225228 BIO_meth_free(ossl_bio_meth);
226229 ossl_bio_meth = NULL;
227230 ossl_raise(eOSSLError, "BIO_meth_set_*");
228231 }
232+
233+ nonblock_kwargs = rb_hash_new();
234+ rb_hash_aset(nonblock_kwargs, ID2SYM(rb_intern("exception")), Qfalse);
235+ rb_global_variable(&nonblock_kwargs);
229236}
0 commit comments