Add zero copy read and write api for bio pairs.
Also add functionality for setting external buffers to give the
caller better control of the buffers. This is typical needed if OS
sockets can outlive the bio pair.
Change-Id: I500f0c522011ce76e9a9bce5d7b43c93d9d11457
diff --git a/include/openssl/bio.h b/include/openssl/bio.h
index 547a36a..3f64dd3 100644
--- a/include/openssl/bio.h
+++ b/include/openssl/bio.h
@@ -586,6 +586,18 @@
OPENSSL_EXPORT int BIO_new_bio_pair(BIO **out1, size_t writebuf1, BIO **out2,
size_t writebuf2);
+/* BIO_new_bio_pair_external_buf is the same as |BIO_new_bio_pair| with the
+ * difference that the caller keeps ownership of the write buffers
+ * |ext_writebuf1| and |ext_writebuf2|. This is useful when using zero copy API
+ * for read and write operations, in cases where the buffers need to outlive the
+ * BIO pairs. It returns one on success and zero on error. */
+OPENSSL_EXPORT int BIO_new_bio_pair_external_buf(BIO** bio1_p,
+ size_t writebuf1,
+ uint8_t* ext_writebuf1,
+ BIO** bio2_p,
+ size_t writebuf2,
+ uint8_t* ext_writebuf2);
+
/* BIO_s_bio returns the method for a BIO pair. */
OPENSSL_EXPORT const BIO_METHOD *BIO_s_bio(void);
@@ -604,6 +616,63 @@
OPENSSL_EXPORT int BIO_shutdown_wr(BIO *bio);
+/* Zero copy versions of BIO_read and BIO_write for BIO pairs. */
+
+/* BIO_zero_copy_get_read_buf initiates a zero copy read operation.
+ * |out_read_buf| is set to the internal read buffer, and |out_buf_offset| is
+ * set to the current read position of |out_read_buf|. The number of bytes
+ * available for read from |out_read_buf| + |out_buf_offset| is returned in
+ * |out_available_bytes|. Note that this function might report fewer bytes
+ * available than |BIO_pending|, if the internal ring buffer is wrapped. It
+ * returns one on success. In case of error it returns zero and pushes to the
+ * error stack.
+ *
+ * The zero copy read operation is completed by calling
+ * |BIO_zero_copy_get_read_buf_done|. Neither |BIO_zero_copy_get_read_buf| nor
+ * any other I/O read operation may be called while a zero copy read operation
+ * is active. */
+OPENSSL_EXPORT int BIO_zero_copy_get_read_buf(BIO* bio,
+ uint8_t** out_read_buf,
+ size_t* out_buf_offset,
+ size_t* out_available_bytes);
+
+/* BIO_zero_copy_get_read_buf_done must be called after reading from a BIO using
+ * |BIO_zero_copy_get_read_buf| to finish the read operation. The |bytes_read|
+ * argument is the number of bytes read.
+ *
+ * It returns one on success. In case of error it returns zero and pushes to the
+ * error stack. */
+OPENSSL_EXPORT int BIO_zero_copy_get_read_buf_done(BIO* bio, size_t bytes_read);
+
+/* BIO_zero_copy_get_write_buf_done initiates a zero copy write operation.
+ * |out_write_buf| is set to to the internal write buffer, and |out_buf_offset|
+ * is set to the current write position of |out_write_buf|.
+ * The number of bytes available for write from |out_write_buf| +
+ * |out_buf_offset| is returned in |out_available_bytes|. Note that this
+ * function might report fewer bytes available than
+ * |BIO_ctrl_get_write_guarantee|, if the internal buffer is wrapped. It returns
+ * one on success. In case of error it returns zero and pushes to the error
+ * stack.
+ *
+ * The zero copy write operation is completed by calling
+ * |BIO_zero_copy_write_buf_don|e. Neither |BIO_zero_copy_get_write_buf_done|
+ * nor any other I/O write operation may be called while a zero copy write
+ * operation is active. */
+OPENSSL_EXPORT int BIO_zero_copy_get_write_buf(BIO* bio,
+ uint8_t** out_write_buf,
+ size_t* out_buf_offset,
+ size_t* out_available_bytes);
+
+/* BIO_zero_copy_write_buf_done must be called after writing to a BIO using
+ * |BIO_zero_copy_get_write_buf_done| to finish the write operation. The
+ * |bytes_written| argument gives the number of bytes written.
+ *
+ * It returns one on success. In case of error it returns zero and pushes to the
+ * error stack. */
+OPENSSL_EXPORT int BIO_zero_copy_get_write_buf_done(BIO* bio,
+ size_t bytes_written);
+
+
/* BIO_NOCLOSE and |BIO_CLOSE| can be used as symbolic arguments when a "close
* flag" is passed to a BIO function. */
#define BIO_NOCLOSE 0
@@ -804,6 +873,10 @@
#define BIO_F_bio_ip_and_port_to_socket_and_addr 113
#define BIO_F_bio_write 114
#define BIO_F_BIO_ctrl 115
+#define BIO_F_BIO_zero_copy_get_write_buf 116
+#define BIO_F_BIO_zero_copy_get_write_buf_done 117
+#define BIO_F_BIO_zero_copy_get_read_buf 118
+#define BIO_F_BIO_zero_copy_get_read_buf_done 119
#define BIO_R_UNSUPPORTED_METHOD 100
#define BIO_R_NO_PORT_SPECIFIED 101
#define BIO_R_NO_HOSTNAME_SPECIFIED 102