Skip to main content

Bio

Struct Bio 

Source
pub struct Bio { /* private fields */ }
Expand description

Shared ownership wrapper around a BIO*.

Used where OpenSSL takes ownership of a BIO (e.g. SSL_set_bio) or where the same BIO must be reachable from multiple Rust values. Implemented with BIO_up_ref / BIO_free.

Implementations§

Source§

impl Bio

Source

pub fn new_pair() -> Result<(Self, Self), ErrorStack>

Create a linked in-memory BIO pair suitable for in-process TLS.

Returns (bio1, bio2) where data written to bio1 is readable from bio2 and vice-versa. Pass each half to crate::ssl::Ssl::set_bio_duplex on the client and server Ssl objects respectively.

§Errors

Returns Err if OpenSSL fails to allocate the pair.

Examples found in repository?
examples/ssl.rs (line 62)
14fn main() -> Result<(), Box<dyn std::error::Error>> {
15    // ── Key pair and self-signed certificate ───────────────────────────────────
16
17    let mut kgen = KeygenCtx::new(c"ED25519")?;
18    let priv_key = kgen.generate()?;
19    let pub_key = native_ossl::pkey::Pkey::<native_ossl::pkey::Public>::from(priv_key.clone());
20
21    let mut name = X509NameOwned::new()?;
22    name.add_entry_by_txt(c"CN", b"localhost")?;
23
24    let cert = X509Builder::new()?
25        .set_version(2)?
26        .set_serial_number(1)?
27        .set_not_before_offset(0)?
28        .set_not_after_offset(86400)?
29        .set_subject_name(&name)?
30        .set_issuer_name(&name)?
31        .set_public_key(&pub_key)?
32        .sign(&priv_key, None)?
33        .build();
34
35    // ── Server context ─────────────────────────────────────────────────────────
36
37    let server_ctx = SslCtx::new_server()?;
38    server_ctx.set_min_proto_version(TlsVersion::Tls13)?;
39    server_ctx.use_certificate(&cert)?;
40    server_ctx.use_private_key(&priv_key)?;
41    server_ctx.check_private_key()?;
42
43    // ── Client context ─────────────────────────────────────────────────────────
44
45    let client_ctx = SslCtx::new_client()?;
46    client_ctx.set_min_proto_version(TlsVersion::Tls13)?;
47    // Skip certificate verification for this self-signed example.
48    client_ctx.set_verify(SslVerifyMode::NONE);
49
50    // ── SSL objects ────────────────────────────────────────────────────────────
51
52    let mut client = client_ctx.new_ssl()?;
53    let mut server = server_ctx.new_ssl()?;
54
55    client.set_connect_state();
56    client.set_hostname(c"localhost")?;
57    server.set_accept_state();
58
59    // ── In-process BIO pair ────────────────────────────────────────────────────
60    // Data written to client_bio is readable from server_bio and vice-versa.
61
62    let (client_bio, server_bio) = Bio::new_pair()?;
63    client.set_bio_duplex(client_bio);
64    server.set_bio_duplex(server_bio);
65
66    // ── Drive the handshake ────────────────────────────────────────────────────
67    // Alternate between client and server until both report success.
68
69    let mut client_done = false;
70    let mut server_done = false;
71
72    for step in 0..20 {
73        if !client_done {
74            match client.connect() {
75                Ok(()) => {
76                    client_done = true;
77                    println!("Client handshake done at step {step}");
78                }
79                Err(SslIoError::WantRead | SslIoError::WantWrite) => {}
80                Err(e) => return Err(format!("client error: {e}").into()),
81            }
82        }
83        if !server_done {
84            match server.accept() {
85                Ok(()) => {
86                    server_done = true;
87                    println!("Server handshake done at step {step}");
88                }
89                Err(SslIoError::WantRead | SslIoError::WantWrite) => {}
90                Err(e) => return Err(format!("server error: {e}").into()),
91            }
92        }
93        if client_done && server_done {
94            break;
95        }
96    }
97    assert!(client_done && server_done, "handshake did not complete");
98
99    // ── Inspect the peer certificate on the client ─────────────────────────────
100
101    if let Some(peer_cert) = client.peer_certificate() {
102        if let Some(subject) = peer_cert.subject_name().to_string() {
103            println!("Server cert subject: {subject}");
104        }
105    }
106
107    // ── Application data exchange ──────────────────────────────────────────────
108
109    let request = b"GET / HTTP/1.0\r\n\r\n";
110    let response = b"HTTP/1.0 200 OK\r\n\r\nHello, TLS!";
111
112    let written = client.write(request)?;
113    assert_eq!(written, request.len());
114
115    let mut rbuf = [0u8; 64];
116    let n = server.read(&mut rbuf)?;
117    assert_eq!(&rbuf[..n], request);
118    println!("Server received: {:?}", std::str::from_utf8(&rbuf[..n])?);
119
120    let written = server.write(response)?;
121    assert_eq!(written, response.len());
122
123    let n = client.read(&mut rbuf)?;
124    assert_eq!(&rbuf[..n], response);
125    println!("Client received: {:?}", std::str::from_utf8(&rbuf[..n])?);
126
127    println!("In-process TLS 1.3 round-trip: OK");
128
129    Ok(())
130}
Source

pub fn read(&mut self, buf: &mut [u8]) -> Result<usize, ErrorStack>

Read bytes from the BIO into buf.

Returns the number of bytes actually read, which may be less than buf.len() if fewer bytes are available.

§Errors

Returns Err on I/O error or EOF (when BIO_read returns -1).

Source

pub fn read_ex(&mut self, buf: &mut [u8]) -> Result<usize, ErrorStack>

Read bytes from the BIO, reporting the exact number of bytes read.

On success returns the number of bytes placed into buf.

§Errors

Returns Err if BIO_read_ex reports failure (returns 0).

Source

pub fn write(&mut self, buf: &[u8]) -> Result<usize, ErrorStack>

Write buf into the BIO.

Returns the number of bytes actually written.

§Errors

Returns Err on I/O error (when BIO_write returns -1).

Source

pub fn push(self, next: Bio) -> Bio

Append next after self in the BIO chain.

Ownership of next is transferred into the chain; it must not be freed separately. Returns self with the chain extended.

Corresponds to BIO_push(self, next).

Source

pub fn pop(&mut self) -> Option<Bio>

Remove self from its chain and return the rest of the chain.

After this call self is a standalone BIO. Returns None if self was the only (or last) element in the chain.

Corresponds to BIO_pop(self).

Source

pub fn next(&self) -> Option<BorrowedBio<'_>>

Return a borrowed view of the next BIO in the chain without consuming self.

The returned BorrowedBio is valid for the lifetime of self and does not free the underlying pointer when dropped.

Returns None if self is the last (or only) BIO in the chain.

Corresponds to BIO_next(self).

Source

pub fn pending(&self) -> usize

Return the number of bytes available for reading from the BIO.

Corresponds to the BIO_pending C macro, implemented via BIO_ctrl(b, BIO_CTRL_PENDING, 0, NULL).

For a mem BIO this is the number of unread bytes in the buffer. For other BIO types the value is type-specific.

Source

pub fn wpending(&self) -> usize

Return the number of bytes still to be written (pending in the write buffer).

Corresponds to the BIO_wpending C macro, implemented via BIO_ctrl(b, BIO_CTRL_WPENDING, 0, NULL).

For most BIO types this is 0 (writes are synchronous). For filter BIOs it reflects bytes buffered but not yet flushed downstream.

Source

pub fn find_type(&self, bio_type: c_int) -> Option<BorrowedBio<'_>>

Search the chain for the first BIO of the given bio_type.

bio_type is one of the BIO_TYPE_* integer constants from OpenSSL (e.g. BIO_TYPE_MEM = 8, BIO_TYPE_BIO = 19).

Returns a borrowed view of the matching BIO, or None if none is found.

Corresponds to BIO_find_type(self, bio_type).

§Errors

Returns None if no BIO of the requested type exists in the chain.

Trait Implementations§

Source§

impl Clone for Bio

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Drop for Bio

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl Send for Bio

Source§

impl Sync for Bio

Auto Trait Implementations§

§

impl Freeze for Bio

§

impl RefUnwindSafe for Bio

§

impl Unpin for Bio

§

impl UnsafeUnpin for Bio

§

impl UnwindSafe for Bio

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.