Skip to content

Commit d725420

Browse files
committed
ham
1 parent ef6508f commit d725420

File tree

1 file changed

+35
-28
lines changed

1 file changed

+35
-28
lines changed

ext/openssl/ossl_bio.c

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* (See the file 'LICENCE'.)
99
*/
1010
#include "ossl.h"
11+
#include <openssl/bio.h>
1112

1213
BIO *
1314
ossl_obj2bio(volatile VALUE *pobj)
@@ -42,7 +43,8 @@ ossl_membio2str(BIO *bio)
4243
}
4344

4445
BIO_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

4749
static void
4850
bio_save_error(BIO *bio, int state)
@@ -77,8 +79,8 @@ ossl_bio_restore_error(BIO *bio)
7779
struct 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

8486
static 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

116115
static 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

129130
struct bread_args {
130131
BIO *bio;
131132
char *data;
132-
size_t dlen;
133-
size_t *readbytes;
133+
int dlen;
134+
int readbytes;
134135
};
135136

136137
static 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

175175
static 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

188190
static 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
213215
Init_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

Comments
 (0)