Skip to content

Commit ea0d242

Browse files
committed
fix bio
1 parent f896d0d commit ea0d242

File tree

1 file changed

+42
-32
lines changed

1 file changed

+42
-32
lines changed

stdlib/src/ssl.rs

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1632,20 +1632,7 @@ mod _ssl {
16321632
}
16331633
}
16341634

1635-
// Set BIOs using SSL_set_bio
1636-
// BIOs are reference counted and SSL_set_bio borrows our reference
1637-
// To prevent double free, we need to increment the reference count
1638-
unsafe {
1639-
let inbio_ptr = args.incoming.bio;
1640-
let outbio_ptr = args.outgoing.bio;
1641-
1642-
// Increment reference counts
1643-
BIO_up_ref(inbio_ptr);
1644-
BIO_up_ref(outbio_ptr);
1645-
1646-
// Set BIOs on SSL object
1647-
sys::SSL_set_bio(ssl.as_ptr(), inbio_ptr, outbio_ptr);
1648-
}
1635+
// Don't use SSL_set_bio - let SslStream drive I/O through BioStream Read/Write
16491636

16501637
// Configure post-handshake authentication (PHA)
16511638
#[cfg(ossl111)]
@@ -1672,8 +1659,8 @@ mod _ssl {
16721659

16731660
// Create a BioStream wrapper (dummy, actual IO goes through BIOs)
16741661
let bio_stream = BioStream {
1675-
_inbio: args.incoming,
1676-
_outbio: args.outgoing,
1662+
inbio: args.incoming,
1663+
outbio: args.outgoing,
16771664
};
16781665

16791666
// Create SslStream with BioStream
@@ -1841,32 +1828,55 @@ mod _ssl {
18411828

18421829
// BIO stream wrapper to implement Read/Write traits for MemoryBIO
18431830
struct BioStream {
1844-
_inbio: PyRef<PySslMemoryBio>,
1845-
_outbio: PyRef<PySslMemoryBio>,
1831+
inbio: PyRef<PySslMemoryBio>,
1832+
outbio: PyRef<PySslMemoryBio>,
18461833
}
18471834

18481835
impl Read for BioStream {
1849-
fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> {
1850-
// BIO mode doesn't use actual IO - data is transferred via MemoryBIO
1851-
// This should never be called as SSL will directly use the BIOs
1852-
Err(std::io::Error::new(
1853-
std::io::ErrorKind::Unsupported,
1854-
"BIO mode doesn't support direct read",
1855-
))
1836+
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
1837+
// Read from incoming MemoryBIO
1838+
unsafe {
1839+
let nbytes = sys::BIO_read(
1840+
self.inbio.bio,
1841+
buf.as_mut_ptr() as *mut _,
1842+
buf.len().min(i32::MAX as usize) as i32,
1843+
);
1844+
if nbytes < 0 {
1845+
// BIO_read returns -1 on error or when no data is available
1846+
// Check if it's a retry condition (WANT_READ)
1847+
Err(std::io::Error::new(
1848+
std::io::ErrorKind::WouldBlock,
1849+
"BIO has no data available",
1850+
))
1851+
} else {
1852+
Ok(nbytes as usize)
1853+
}
1854+
}
18561855
}
18571856
}
18581857

18591858
impl Write for BioStream {
1860-
fn write(&mut self, _buf: &[u8]) -> std::io::Result<usize> {
1861-
// BIO mode doesn't use actual IO - data is transferred via MemoryBIO
1862-
// This should never be called as SSL will directly use the BIOs
1863-
Err(std::io::Error::new(
1864-
std::io::ErrorKind::Unsupported,
1865-
"BIO mode doesn't support direct write",
1866-
))
1859+
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
1860+
// Write to outgoing MemoryBIO
1861+
unsafe {
1862+
let nbytes = sys::BIO_write(
1863+
self.outbio.bio,
1864+
buf.as_ptr() as *const _,
1865+
buf.len().min(i32::MAX as usize) as i32,
1866+
);
1867+
if nbytes < 0 {
1868+
Err(std::io::Error::new(
1869+
std::io::ErrorKind::Other,
1870+
"BIO write failed",
1871+
))
1872+
} else {
1873+
Ok(nbytes as usize)
1874+
}
1875+
}
18671876
}
18681877

18691878
fn flush(&mut self) -> std::io::Result<()> {
1879+
// MemoryBIO doesn't need flushing
18701880
Ok(())
18711881
}
18721882
}

0 commit comments

Comments
 (0)