use ::std::io;
use bun_uws_sys::us_bun_verify_error_t;
use bun_windows_sys as w;
use bun_windows_sys::kernel32::{
DisconnectNamedPipe, FlushFileBuffers, ReadFile, WriteFile,
};
pub struct WindowsNamedPipe {
handle: w::HANDLE,
established: bool,
closed: bool,
shutdown_write: bool,
shutdown_read: bool,
paused: bool,
ssl: Option<*mut bun_boringssl_sys::SSL>,
ssl_error: us_bun_verify_error_t,
timeout_seconds: u32,
}
unsafe impl Send for WindowsNamedPipe {}
unsafe impl Sync for WindowsNamedPipe {}
impl WindowsNamedPipe {
pub fn from_handle(handle: w::HANDLE) -> Box<Self> {
Box::new(Self {
handle,
established: true,
closed: false,
shutdown_write: false,
shutdown_read: false,
paused: false,
ssl: None,
ssl_error: us_bun_verify_error_t {
error_no: 0,
code: ::std::ptr::null(),
reason: ::std::ptr::null(),
},
timeout_seconds: 0,
})
}
fn write_all(&self, mut bytes: &[u8]) -> io::Result<()> {
while !bytes.is_empty() {
let mut written: w::DWORD = 0;
let ok = unsafe {
WriteFile(
self.handle,
bytes.as_ptr(),
bytes.len() as w::DWORD,
&mut written,
::std::ptr::null_mut(),
)
};
if ok == 0 {
return Err(io::Error::last_os_error());
}
if written == 0 {
return Err(io::Error::new(
io::ErrorKind::WriteZero,
"WindowsNamedPipe: write made no progress",
));
}
bytes = &bytes[written as usize..];
}
Ok(())
}
}
#[unsafe(no_mangle)]
pub extern "C" fn WindowsNamedPipe__ssl(this: &WindowsNamedPipe) -> *mut bun_boringssl_sys::SSL {
this.ssl.unwrap_or(::std::ptr::null_mut())
}
#[unsafe(no_mangle)]
pub extern "C" fn WindowsNamedPipe__ssl_error(
this: &WindowsNamedPipe,
) -> us_bun_verify_error_t {
this.ssl_error
}
#[unsafe(no_mangle)]
pub extern "C" fn WindowsNamedPipe__is_established(this: &WindowsNamedPipe) -> bool {
this.established && !this.closed
}
#[unsafe(no_mangle)]
pub extern "C" fn WindowsNamedPipe__is_closed(this: &WindowsNamedPipe) -> bool {
this.closed
}
#[unsafe(no_mangle)]
pub extern "C" fn WindowsNamedPipe__is_shutdown(this: &WindowsNamedPipe) -> bool {
this.shutdown_write
}
#[unsafe(no_mangle)]
pub extern "C" fn WindowsNamedPipe__pause_stream(this: &mut WindowsNamedPipe) -> bool {
if this.closed {
return false;
}
this.paused = true;
true
}
#[unsafe(no_mangle)]
pub extern "C" fn WindowsNamedPipe__resume_stream(this: &mut WindowsNamedPipe) -> bool {
if this.closed {
return false;
}
this.paused = false;
true
}
#[unsafe(no_mangle)]
pub extern "C" fn WindowsNamedPipe__flush(this: &mut WindowsNamedPipe) {
if !this.closed && !this.shutdown_write {
unsafe { FlushFileBuffers(this.handle) };
}
}
#[unsafe(no_mangle)]
pub extern "C" fn WindowsNamedPipe__set_timeout(this: &mut WindowsNamedPipe, seconds: u32) {
this.timeout_seconds = seconds;
}
#[unsafe(no_mangle)]
pub extern "C" fn WindowsNamedPipe__encode_and_write(
this: &mut WindowsNamedPipe,
ptr: *const u8,
len: usize,
) -> i32 {
if this.closed || this.shutdown_write {
return -1;
}
let bytes = unsafe { ::std::slice::from_raw_parts(ptr, len) };
match this.write_all(bytes) {
Ok(()) => len as i32,
Err(_) => -1,
}
}
#[unsafe(no_mangle)]
pub extern "C" fn WindowsNamedPipe__raw_write(
this: &mut WindowsNamedPipe,
ptr: *const u8,
len: usize,
) -> i32 {
WindowsNamedPipe__encode_and_write(this, ptr, len)
}
#[unsafe(no_mangle)]
pub extern "C" fn WindowsNamedPipe__shutdown(this: &mut WindowsNamedPipe) {
if this.closed {
return;
}
this.shutdown_write = true;
unsafe { FlushFileBuffers(this.handle) };
}
#[unsafe(no_mangle)]
pub extern "C" fn WindowsNamedPipe__shutdown_read(this: &mut WindowsNamedPipe) {
this.shutdown_read = true;
}
#[unsafe(no_mangle)]
pub extern "C" fn WindowsNamedPipe__close(this: &mut WindowsNamedPipe) {
if this.closed {
return;
}
this.closed = true;
unsafe {
DisconnectNamedPipe(this.handle);
w::CloseHandle(this.handle);
}
}