Skip to content

Commit

Permalink
ham
Browse files Browse the repository at this point in the history
  • Loading branch information
rhenium committed Mar 23, 2024
1 parent ef6508f commit d725420
Showing 1 changed file with 35 additions and 28 deletions.
63 changes: 35 additions & 28 deletions ext/openssl/ossl_bio.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* (See the file 'LICENCE'.)
*/
#include "ossl.h"
#include <openssl/bio.h>

BIO *
ossl_obj2bio(volatile VALUE *pobj)
Expand Down Expand Up @@ -42,7 +43,8 @@ ossl_membio2str(BIO *bio)
}

BIO_METHOD *ossl_bio_meth;
static int bio_state_idx, bio_errinfo_idx;
static int bio_state_idx, bio_errinfo_idx, bio_eof_idx;
static VALUE nonblock_kwargs;

static void
bio_save_error(BIO *bio, int state)
Expand Down Expand Up @@ -77,8 +79,8 @@ ossl_bio_restore_error(BIO *bio)
struct bwrite_args {
BIO *bio;
const char *data;
size_t dlen;
size_t *written;
int dlen;
int written;
};

static VALUE
Expand All @@ -88,15 +90,12 @@ bio_bwrite0(VALUE args)
VALUE io = (VALUE)BIO_get_data(p->bio);
BIO_clear_retry_flags(p->bio);

VALUE str = rb_str_new_static(p->data, p->dlen);
VALUE kwargs = rb_hash_new();
rb_hash_aset(kwargs, ID2SYM(rb_intern("exception")), Qfalse);
VALUE funcallargs[] = { str, kwargs };
VALUE fargs[] = { rb_str_new_static(p->data, p->dlen), nonblock_kwargs };
VALUE ret = rb_funcallv_public_kw(io, rb_intern("write_nonblock"),
2, funcallargs, RB_PASS_KEYWORDS);
2, fargs, RB_PASS_KEYWORDS);

if (RB_INTEGER_TYPE_P(ret)) {
*p->written = NUM2SIZET(ret);
p->written = NUM2INT(ret);
return INT2FIX(1);
}
else if (ret == ID2SYM(rb_intern("wait_readable"))) {
Expand All @@ -114,23 +113,25 @@ bio_bwrite0(VALUE args)
}

static int
bio_bwrite(BIO *bio, const char *data, size_t dlen, size_t *written)
bio_bwrite(BIO *bio, const char *data, int dlen)
{
struct bwrite_args args = { bio, data, dlen, written };
struct bwrite_args args = { bio, data, dlen, 0 };
int state;

VALUE ret = rb_protect(bio_bwrite0, (VALUE)&args, &state);
bio_save_error(bio, state);
if (state)
return 0;
return FIX2INT(ret);
if (FIX2INT(ret))
return args.written;
return -1;
}

struct bread_args {
BIO *bio;
char *data;
size_t dlen;
size_t *readbytes;
int dlen;
int readbytes;
};

static VALUE
Expand All @@ -140,22 +141,21 @@ bio_bread0(VALUE args)
VALUE io = (VALUE)BIO_get_data(p->bio);
BIO_clear_retry_flags(p->bio);

VALUE kwargs = rb_hash_new();
rb_hash_aset(kwargs, ID2SYM(rb_intern("exception")), Qfalse);
VALUE funcallargs[] = { SIZET2NUM(p->dlen), kwargs };
VALUE fargs[] = { INT2NUM(p->dlen), nonblock_kwargs };
VALUE ret = rb_funcallv_public_kw(io, rb_intern("read_nonblock"),
2, funcallargs, RB_PASS_KEYWORDS);
2, fargs, RB_PASS_KEYWORDS);

if (RB_TYPE_P(ret, T_STRING)) {
size_t len = (size_t)RSTRING_LEN(ret);
int len = RSTRING_LENINT(ret);
if (len > p->dlen)
rb_raise(rb_eTypeError, "read_nonblock returned too much data");
memcpy(p->data, RSTRING_PTR(ret), len);
*p->readbytes = len;
p->readbytes = len;
return INT2FIX(1);
}
else if (NIL_P(ret)) {
BIO_set_flags(p->bio, BIO_FLAGS_IN_EOF);
// In OpenSSL 3.0 or later: BIO_set_flags(p->bio, BIO_FLAGS_IN_EOF);
BIO_set_ex_data(p->bio, bio_eof_idx, (void *)1);
return INT2FIX(0);
}
else if (ret == ID2SYM(rb_intern("wait_readable"))) {
Expand All @@ -173,16 +173,18 @@ bio_bread0(VALUE args)
}

static int
bio_bread(BIO *bio, char *data, size_t dlen, size_t *readbytes)
bio_bread(BIO *bio, char *data, int dlen)
{
struct bread_args args = { bio, data, dlen, readbytes };
struct bread_args args = { bio, data, dlen, 0 };
int state;

VALUE ret = rb_protect(bio_bread0, (VALUE)&args, &state);
bio_save_error(bio, state);
if (state)
return 0;
return FIX2INT(ret);
if (FIX2INT(ret))
return args.readbytes;
return -1;
}

static VALUE
Expand All @@ -199,7 +201,7 @@ bio_ctrl(BIO *bio, int cmd, long larg, void *parg)

switch (cmd) {
case BIO_CTRL_EOF:
return BIO_test_flags(bio, BIO_FLAGS_IN_EOF);
return (int)(uintptr_t)BIO_get_ex_data(bio, bio_eof_idx);
case BIO_CTRL_FLUSH:
rb_protect(bio_flush0, (VALUE)bio, &state);
bio_save_error(bio, state);
Expand All @@ -213,17 +215,22 @@ void
Init_ossl_bio(void)
{
if ((bio_state_idx = BIO_get_ex_new_index(0, NULL, NULL, NULL, NULL)) < 0 ||
(bio_errinfo_idx = BIO_get_ex_new_index(0, NULL, NULL, NULL, NULL)) < 0)
(bio_errinfo_idx = BIO_get_ex_new_index(0, NULL, NULL, NULL, NULL)) < 0 ||
(bio_eof_idx = BIO_get_ex_new_index(0, NULL, NULL, NULL, NULL)) < 0)
ossl_raise(eOSSLError, "BIO_get_ex_new_index");

ossl_bio_meth = BIO_meth_new(BIO_TYPE_SOURCE_SINK, "Ruby IO-like object");
if (!ossl_bio_meth)
ossl_raise(eOSSLError, "BIO_meth_new");
if (!BIO_meth_set_write_ex(ossl_bio_meth, bio_bwrite) ||
!BIO_meth_set_read_ex(ossl_bio_meth, bio_bread) ||
if (!BIO_meth_set_write(ossl_bio_meth, bio_bwrite) ||
!BIO_meth_set_read(ossl_bio_meth, bio_bread) ||
!BIO_meth_set_ctrl(ossl_bio_meth, bio_ctrl)) {
BIO_meth_free(ossl_bio_meth);
ossl_bio_meth = NULL;
ossl_raise(eOSSLError, "BIO_meth_set_*");
}

nonblock_kwargs = rb_hash_new();
rb_hash_aset(nonblock_kwargs, ID2SYM(rb_intern("exception")), Qfalse);
rb_global_variable(&nonblock_kwargs);
}

0 comments on commit d725420

Please sign in to comment.