doc: add documentation for BIO_nread0, BIO_nread, BIO_nwrite0, BIO_nwrite

Document the non-copying interface functions for BIO pairs that allow
direct access to the internal buffer:
- BIO_nread0/BIO_nread for zero-copy reading
- BIO_nwrite0/BIO_nwrite for zero-copy writing

Also add return value documentation for these functions and remove
the placeholder "[XXXXX: More return values need to be added here]".

Fixes #16366

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
Reviewed-by: Nikola Pajkovsky <nikolap@openssl.org>
MergeDate: Wed May  6 14:51:27 2026
(Merged from https://github.com/openssl/openssl/pull/29849)
This commit is contained in:
kovan
2026-01-29 15:28:59 +01:00
committed by Norbert Pocs
parent c5908ee434
commit bd85fd7cde
2 changed files with 80 additions and 5 deletions
+80 -1
View File
@@ -5,7 +5,8 @@
BIO_s_bio, BIO_make_bio_pair, BIO_destroy_bio_pair, BIO_shutdown_wr,
BIO_set_write_buf_size, BIO_get_write_buf_size, BIO_new_bio_pair,
BIO_get_write_guarantee, BIO_ctrl_get_write_guarantee, BIO_get_read_request,
BIO_ctrl_get_read_request, BIO_ctrl_reset_read_request - BIO pair BIO
BIO_ctrl_get_read_request, BIO_ctrl_reset_read_request,
BIO_nread0, BIO_nread, BIO_nwrite0, BIO_nwrite - BIO pair BIO
=head1 SYNOPSIS
@@ -28,6 +29,11 @@ BIO_ctrl_get_read_request, BIO_ctrl_reset_read_request - BIO pair BIO
size_t BIO_ctrl_get_read_request(BIO *b);
int BIO_ctrl_reset_read_request(BIO *b);
int BIO_nread0(BIO *bio, char **buf);
int BIO_nread(BIO *bio, char **buf, int num);
int BIO_nwrite0(BIO *bio, char **buf);
int BIO_nwrite(BIO *bio, char **buf, int num);
=head1 DESCRIPTION
BIO_s_bio() returns the method for a BIO pair. A BIO pair is a pair of source/sink
@@ -98,6 +104,44 @@ than that returned by BIO_get_write_guarantee().
BIO_ctrl_reset_read_request() can also be used to reset the value returned by
BIO_get_read_request() to zero.
=head2 Non-copying Interface
BIO_nread0(), BIO_nread(), BIO_nwrite0(), and BIO_nwrite() provide a non-copying
interface for reading from and writing to BIO pairs. These functions allow
direct access to the internal buffer, avoiding the overhead of copying data.
BIO_nread0() returns in B<*buf> a pointer to the start of the available data
in the peer's write buffer and returns the number of bytes available.
This allows reading directly from the buffer without copying.
It does not consume the data; a subsequent call to BIO_nread() is needed
to advance the buffer position.
BIO_nread() is similar to BIO_nread0() but also advances the read position
by up to B<num> bytes. The actual number of bytes consumed is returned.
The B<*buf> pointer is set to the start of the data that was consumed.
Since the data is considered consumed after this call, the pointer returned
by BIO_nread() should not be used afterwards unless the caller also
controls the writing side. The typical pattern is to call BIO_nread0() first,
use the data, and then call BIO_nread() to consume it.
BIO_nwrite0() returns in B<*buf> a pointer to the start of the available
space in the write buffer and returns the number of bytes that can be written.
This allows writing directly to the buffer without copying.
It does not commit the data; a subsequent call to BIO_nwrite() is needed
to update the buffer length.
BIO_nwrite() is similar to BIO_nwrite0() but also commits up to B<num> bytes
as written. The actual number of bytes committed is returned.
The B<*buf> pointer is set to the start of the region that was committed.
BIO_nwrite() should only be called after the data has actually been written
to the buffer obtained from BIO_nwrite0(), since committing signals data
availability to the reading side.
Note that due to the ring buffer implementation, if wrapping around would be
required, BIO_nread0() and BIO_nwrite0() may return less than the total
available space. In such cases, a second call may be needed to access the
remaining data or space.
=head1 NOTES
Both halves of a BIO pair should be freed. That is even if one half is implicit
@@ -133,6 +177,17 @@ locations for B<bio1> and B<bio2>. Check the error stack for more information.
[XXXXX: More return values need to be added here]
BIO_nread0() returns the number of bytes available for reading, 0 if the peer
has closed and no data remains (EOF), or -1 if no data is currently available
(retry may be appropriate). If the BIO is not initialized, -2 is returned.
BIO_nwrite0() returns the number of bytes of space available for writing, or -1
if no space is currently available (retry may be appropriate) or the BIO has
been closed. If the BIO is not initialized, -2 is returned.
BIO_nread() and BIO_nwrite() return the number of bytes consumed or committed
respectively, or the same error values as BIO_nread0() and BIO_nwrite0().
=head1 EXAMPLES
The BIO pair can be used to have full control over the network access of an
@@ -176,6 +231,30 @@ and must be transferred to the network. Use BIO_ctrl_get_read_request() to
find out, how many bytes must be written into the buffer before the
SSL_operation() can successfully be continued.
A typical usage pattern for the non-copying write interface is:
int ret;
char *buf;
ret = BIO_nwrite0(bio, &buf);
if (ret > 0) {
/* write up to 'ret' bytes directly to 'buf' */
memcpy(buf, data, len);
BIO_nwrite(bio, &buf, len); /* commit the write */
}
A typical usage pattern for the non-copying read interface is:
int ret;
char *buf;
ret = BIO_nread0(bio, &buf);
if (ret > 0) {
/* read up to 'ret' bytes directly from 'buf' */
process_data(buf, ret);
BIO_nread(bio, &buf, ret); /* consume the data */
}
=head1 WARNINGS
As the data is buffered, SSL_operation() may return with an ERROR_SSL_WANT_READ
-4
View File
@@ -189,12 +189,8 @@ BIO_method_name(3)
BIO_new_NDEF(3)
BIO_new_PKCS7(3)
BIO_new_dgram_sctp(3)
BIO_nread(3)
BIO_nread0(3)
BIO_number_read(3)
BIO_number_written(3)
BIO_nwrite(3)
BIO_nwrite0(3)
BIO_s_datagram_sctp(3)
BIO_s_log(3)
BIO_set_tcp_ndelay(3)