ustream-ssl: add support for using a fd instead of ustream as backing
[project/ustream-ssl.git] / ustream-io-openssl.c
index 9a22ff0a1c4cfbd891b8b377b370cbb1f7f57919..4ca77deecafabdba3e193e87a75a169474108664 100644 (file)
 #include <libubox/ustream.h>
 
 #include "ustream-ssl.h"
+#include "openssl_bio_compat.h"
 #include "ustream-internal.h"
 
 static int
 s_ustream_new(BIO *b)
 {
-       b->init = 1;
-       b->num = 0;
-       b->ptr = NULL;
-       b->flags = 0;
+       BIO_set_init(b, 1);
+       BIO_set_data(b, NULL);
+       BIO_clear_flags(b, ~0);
        return 1;
 }
 
@@ -39,27 +39,27 @@ s_ustream_free(BIO *b)
        if (!b)
                return 0;
 
-       b->ptr = NULL;
-       b->init = 0;
-       b->flags = 0;
+       BIO_set_data(b, NULL);
+       BIO_set_init(b, 0);
+       BIO_clear_flags(b, ~0);
        return 1;
 }
 
 static int
 s_ustream_read(BIO *b, char *buf, int len)
 {
-       struct ustream *s;
+       struct bio_ctx *ctx;
        char *sbuf;
        int slen;
 
        if (!buf || len <= 0)
                return 0;
 
-       s = (struct ustream *)b->ptr;
-       if (!s)
+       ctx = (struct bio_ctx *)BIO_get_data(b);
+       if (!ctx || !ctx->stream)
                return 0;
 
-       sbuf = ustream_get_read_buf(s, &slen);
+       sbuf = ustream_get_read_buf(ctx->stream, &slen);
 
        BIO_clear_retry_flags(b);
        if (!slen) {
@@ -71,7 +71,7 @@ s_ustream_read(BIO *b, char *buf, int len)
                slen = len;
 
        memcpy(buf, sbuf, slen);
-       ustream_consume(s, slen);
+       ustream_consume(ctx->stream, slen);
 
        return slen;
 }
@@ -79,19 +79,19 @@ s_ustream_read(BIO *b, char *buf, int len)
 static int
 s_ustream_write(BIO *b, const char *buf, int len)
 {
-       struct ustream *s;
+       struct bio_ctx *ctx;
 
        if (!buf || len <= 0)
                return 0;
 
-       s = (struct ustream *)b->ptr;
-       if (!s)
+       ctx = (struct bio_ctx *)BIO_get_data(b);
+       if (!ctx || !ctx->stream)
                return 0;
 
-       if (s->write_error)
+       if (ctx->stream->write_error)
                return len;
 
-       return ustream_write(s, buf, len, false);
+       return ustream_write(ctx->stream, buf, len, false);
 }
 
 static int
@@ -116,30 +116,44 @@ static long s_ustream_ctrl(BIO *b, int cmd, long num, void *ptr)
        };
 }
 
-static BIO_METHOD methods_ustream = {
-       100 | BIO_TYPE_SOURCE_SINK,
-       "ustream",
-       s_ustream_write,
-       s_ustream_read,
-       s_ustream_puts,
-       s_ustream_gets,
-       s_ustream_ctrl,
-       s_ustream_new,
-       s_ustream_free,
-       NULL,
-};
-
 static BIO *ustream_bio_new(struct ustream *s)
 {
        BIO *bio;
+       struct bio_ctx *ctx = calloc(1, sizeof(struct bio_ctx));
+
+       ctx->stream = s;
+       ctx->meth = BIO_meth_new(100 | BIO_TYPE_SOURCE_SINK, "ustream");
+
+       BIO_meth_set_write(ctx->meth, s_ustream_write);
+       BIO_meth_set_read(ctx->meth, s_ustream_read);
+       BIO_meth_set_puts(ctx->meth, s_ustream_puts);
+       BIO_meth_set_gets(ctx->meth, s_ustream_gets);
+       BIO_meth_set_ctrl(ctx->meth, s_ustream_ctrl);
+       BIO_meth_set_create(ctx->meth, s_ustream_new);
+       BIO_meth_set_destroy(ctx->meth, s_ustream_free);
+       bio = BIO_new(ctx->meth);
+       BIO_set_data(bio, ctx);
+
+       return bio;
+}
+
+static BIO *fd_bio_new(int fd)
+{
+       BIO *bio = BIO_new(BIO_s_socket());
+
+       BIO_set_fd(bio, fd, BIO_NOCLOSE);
 
-       bio = BIO_new(&methods_ustream);
-       bio->ptr = s;
        return bio;
 }
 
-__hidden void ustream_set_io(void *ctx, void *ssl, struct ustream *conn)
+__hidden void ustream_set_io(struct ustream_ssl *us)
 {
-       BIO *bio = ustream_bio_new(conn);
-       SSL_set_bio(ssl, bio, bio);
+       BIO *bio;
+
+       if (us->conn)
+               bio = ustream_bio_new(us->conn);
+       else
+               bio = fd_bio_new(us->fd.fd);
+
+       SSL_set_bio(us->ssl, bio, bio);
 }