8
8
* (See the file 'LICENCE'.)
9
9
*/
10
10
#include "ossl.h"
11
+ #include <openssl/bio.h>
11
12
12
13
BIO *
13
14
ossl_obj2bio (volatile VALUE * pobj )
@@ -42,7 +43,8 @@ ossl_membio2str(BIO *bio)
42
43
}
43
44
44
45
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 ;
46
48
47
49
static void
48
50
bio_save_error (BIO * bio , int state )
@@ -77,8 +79,8 @@ ossl_bio_restore_error(BIO *bio)
77
79
struct bwrite_args {
78
80
BIO * bio ;
79
81
const char * data ;
80
- size_t dlen ;
81
- size_t * written ;
82
+ int dlen ;
83
+ int written ;
82
84
};
83
85
84
86
static VALUE
@@ -88,15 +90,12 @@ bio_bwrite0(VALUE args)
88
90
VALUE io = (VALUE )BIO_get_data (p -> bio );
89
91
BIO_clear_retry_flags (p -> bio );
90
92
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 };
95
94
VALUE ret = rb_funcallv_public_kw (io , rb_intern ("write_nonblock" ),
96
- 2 , funcallargs , RB_PASS_KEYWORDS );
95
+ 2 , fargs , RB_PASS_KEYWORDS );
97
96
98
97
if (RB_INTEGER_TYPE_P (ret )) {
99
- * p -> written = NUM2SIZET (ret );
98
+ p -> written = NUM2INT (ret );
100
99
return INT2FIX (1 );
101
100
}
102
101
else if (ret == ID2SYM (rb_intern ("wait_readable" ))) {
@@ -114,23 +113,25 @@ bio_bwrite0(VALUE args)
114
113
}
115
114
116
115
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 )
118
117
{
119
- struct bwrite_args args = { bio , data , dlen , written };
118
+ struct bwrite_args args = { bio , data , dlen , 0 };
120
119
int state ;
121
120
122
121
VALUE ret = rb_protect (bio_bwrite0 , (VALUE )& args , & state );
123
122
bio_save_error (bio , state );
124
123
if (state )
125
124
return 0 ;
126
- return FIX2INT (ret );
125
+ if (FIX2INT (ret ))
126
+ return args .written ;
127
+ return -1 ;
127
128
}
128
129
129
130
struct bread_args {
130
131
BIO * bio ;
131
132
char * data ;
132
- size_t dlen ;
133
- size_t * readbytes ;
133
+ int dlen ;
134
+ int readbytes ;
134
135
};
135
136
136
137
static VALUE
@@ -140,22 +141,21 @@ bio_bread0(VALUE args)
140
141
VALUE io = (VALUE )BIO_get_data (p -> bio );
141
142
BIO_clear_retry_flags (p -> bio );
142
143
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 };
146
145
VALUE ret = rb_funcallv_public_kw (io , rb_intern ("read_nonblock" ),
147
- 2 , funcallargs , RB_PASS_KEYWORDS );
146
+ 2 , fargs , RB_PASS_KEYWORDS );
148
147
149
148
if (RB_TYPE_P (ret , T_STRING )) {
150
- size_t len = ( size_t ) RSTRING_LEN (ret );
149
+ int len = RSTRING_LENINT (ret );
151
150
if (len > p -> dlen )
152
151
rb_raise (rb_eTypeError , "read_nonblock returned too much data" );
153
152
memcpy (p -> data , RSTRING_PTR (ret ), len );
154
- * p -> readbytes = len ;
153
+ p -> readbytes = len ;
155
154
return INT2FIX (1 );
156
155
}
157
156
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 );
159
159
return INT2FIX (0 );
160
160
}
161
161
else if (ret == ID2SYM (rb_intern ("wait_readable" ))) {
@@ -173,16 +173,18 @@ bio_bread0(VALUE args)
173
173
}
174
174
175
175
static int
176
- bio_bread (BIO * bio , char * data , size_t dlen , size_t * readbytes )
176
+ bio_bread (BIO * bio , char * data , int dlen )
177
177
{
178
- struct bread_args args = { bio , data , dlen , readbytes };
178
+ struct bread_args args = { bio , data , dlen , 0 };
179
179
int state ;
180
180
181
181
VALUE ret = rb_protect (bio_bread0 , (VALUE )& args , & state );
182
182
bio_save_error (bio , state );
183
183
if (state )
184
184
return 0 ;
185
- return FIX2INT (ret );
185
+ if (FIX2INT (ret ))
186
+ return args .readbytes ;
187
+ return -1 ;
186
188
}
187
189
188
190
static VALUE
@@ -199,7 +201,7 @@ bio_ctrl(BIO *bio, int cmd, long larg, void *parg)
199
201
200
202
switch (cmd ) {
201
203
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 );
203
205
case BIO_CTRL_FLUSH :
204
206
rb_protect (bio_flush0 , (VALUE )bio , & state );
205
207
bio_save_error (bio , state );
@@ -213,17 +215,22 @@ void
213
215
Init_ossl_bio (void )
214
216
{
215
217
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 )
217
220
ossl_raise (eOSSLError , "BIO_get_ex_new_index" );
218
221
219
222
ossl_bio_meth = BIO_meth_new (BIO_TYPE_SOURCE_SINK , "Ruby IO-like object" );
220
223
if (!ossl_bio_meth )
221
224
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 ) ||
224
227
!BIO_meth_set_ctrl (ossl_bio_meth , bio_ctrl )) {
225
228
BIO_meth_free (ossl_bio_meth );
226
229
ossl_bio_meth = NULL ;
227
230
ossl_raise (eOSSLError , "BIO_meth_set_*" );
228
231
}
232
+
233
+ nonblock_kwargs = rb_hash_new ();
234
+ rb_hash_aset (nonblock_kwargs , ID2SYM (rb_intern ("exception" )), Qfalse );
235
+ rb_global_variable (& nonblock_kwargs );
229
236
}
0 commit comments