diff options
author | Bodo Möller <bodo@openssl.org> | 1999-06-07 16:04:45 +0000 |
---|---|---|
committer | Bodo Möller <bodo@openssl.org> | 1999-06-07 16:04:45 +0000 |
commit | 9e06f6f6019198e3f84cbfc9ff5d561400db4d7e (patch) | |
tree | af27198f185af016b1ac4b22cbda027c84e609a5 /crypto/bio/bss_bio.c | |
parent | d4443edc5714712bef2b623102b56a0fc78c1524 (diff) |
Introduce "BIO pairs", which (when finished) will relay data
so that the SSL library can be used for applications that
have to handle all the actual I/O themselves.
Diffstat (limited to 'crypto/bio/bss_bio.c')
-rw-r--r-- | crypto/bio/bss_bio.c | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/crypto/bio/bss_bio.c b/crypto/bio/bss_bio.c new file mode 100644 index 0000000000..5b60f541a1 --- /dev/null +++ b/crypto/bio/bss_bio.c @@ -0,0 +1,258 @@ +/* crypto/bio/bss_bio.c -*- Mode: C; c-file-style: "eay" -*- */ + +/* *** Not yet finished (or even tested). *** */ + +/* Special method for a BIO where the other endpoint is also a BIO + * of this kind, handled by the same thread. + * Such "BIO pairs" are mainly for using the SSL library with I/O interfaces + * for which no specific BIO method is available. */ + +#include <assert.h> +#include <stdlib.h> + +#include <openssl/bio.h> +#include <openssl/err.h> +#include <openssl/crypto.h> + +static int bio_new(BIO *bio); +static int bio_free(BIO *bio); +static int bio_read(BIO *bio, char *buf, int size); +static int bio_write(BIO *bio, char *buf, int num); +static long bio_ctrl(BIO *bio, int cmd, long num, char *ptr); +static int bio_puts(BIO *bio, char *str); + +static int bio_make_pair(BIO *bio1, BIO *bio2); +static void bio_destroy_pair(BIO *bio); + +static BIO_METHOD methods_biop = +{ + BIO_TYPE_BIO, + "BIO pair", + bio_write, + bio_read, + bio_puts, + NULL /* no bio_gets */, + bio_ctrl, + bio_new, + bio_free +}; + +BIO_METHOD *BIO_s_bio(void) + { + return &methods_biop; + } + +struct bio_bio_st +{ + BIO *peer; /* NULL if buf == NULL. + * If peer != NULL, then peer->ptr is also a bio_bio_st, + * and its "peer" member points back to us. */ + + /* This is for what we write (i.e. reading uses peer's struct): */ + int closed; /* valid iff peer != NULL */ + size_t len; /* valid iff buf != NULL; 0 if peer == NULL */ + size_t offset; /* valid iff buf != NULL; 0 if len == 0 */ + size_t size; + char *buf; /* "size" elements (if != NULL) */ +}; + +static int bio_new(BIO *bio) + { + struct bio_bio_st *b; + + b = Malloc(sizeof *b); + if (b == NULL) + return 0; + + b->peer = NULL; + b->size = 17*1024; /* enough for one TLS record (just a default) */ + b->buf = NULL; + + return 1; + } + + +static int bio_free(BIO *bio) + { + struct bio_bio_st *b; + + if (bio == NULL) + return 0; + b = bio->ptr; + + assert(b != NULL); + + if (b->peer) + bio_destroy_pair(bio); + + if (b->buf != NULL) + { + Free(b->buf); + } + + Free(b); + + return 1; + } + + + +static int bio_read(BIO *bio, char *buf, int size) + { + /* XXX */ + return -1; + } + +static int bio_write(BIO *bio, char *buf, int num) + { + /* XXX */ + return -1; + } + +static long bio_ctrl(BIO *bio, int cmd, long num, char *ptr) + { + long ret; + struct bio_bio_st *b = bio->ptr; + + assert(b != NULL); + + switch (cmd) + { + /* XXX Additional commands: */ + /* - Set buffer size */ + /* - make pair */ + /* - destroy pair */ + /* - get number of bytes that the next write will accept */ + /* - send "close" */ + + case BIO_CTRL_RESET: + if (b->buf != NULL) + { + b->len = 0; + b->offset = 0; + } + ret = 0; + break; + + case BIO_CTRL_GET_CLOSE: + ret = bio->shutdown; + break; + + case BIO_CTRL_SET_CLOSE: + bio->shutdown = (int) num; + ret = 1; + break; + + case BIO_CTRL_PENDING: + if (b->peer != NULL) + { + struct bio_bio_st *peer_b =b->peer->ptr; + + ret = (long) peer_b->len; + } + else + ret = 0; + break; + + case BIO_CTRL_WPENDING: + if (b->buf != NULL) + ret = (long) b->len; + else + ret = 0; + break; + + case BIO_CTRL_DUP: + /* XXX */ + + case BIO_CTRL_FLUSH: + ret = 1; + break; + + default: + ret = 0; + } + return ret; + } + +static int bio_puts(BIO *bio, char *str) + { + return bio_write(bio, str, strlen(str)); + } + + + +static int bio_make_pair(BIO *bio1, BIO *bio2) + { + struct bio_bio_st *b1, *b2; + + assert(bio1 != NULL); + assert(bio2 != NULL); + + b1 = bio1->ptr; + b2 = bio2->ptr; + + if (b1->peer != NULL || b2->peer != NULL) + { + BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE); + return 0; + } + + if (b1->buf != NULL) + { + b1->buf = Malloc(b1->size); + if (b1->buf == NULL) + { + BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); + return 0; + } + b1->len = 0; + b1->offset = 0; + } + + if (b2->buf != NULL) + { + b2->buf = Malloc(b2->size); + if (b2->buf == NULL) + { + BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); + return 0; + } + b2->len = 0; + b2->offset = 0; + } + + b1->peer = bio2; + b2->peer = bio1; + + return 1; + } + +static void bio_destroy_pair(BIO *bio) + { + struct bio_bio_st *b = bio->ptr; + + if (b != NULL) + { + BIO *peer_bio = b->peer; + + if (peer_bio != NULL) + { + struct bio_bio_st *peer_b = peer_bio->ptr; + + assert(peer_b != NULL); + assert(peer_b->peer == bio); + + peer_b->peer = NULL; + peer_bio->init = 0; + assert(peer_b->buf != NULL); + peer_b->len = 0; + peer_b->offset = 0; + + b->peer = NULL; + bio->init = 0; + assert(b->buf != NULL); + b->len = 0; + b->offset = 0; + } + } + } |