From ef34d465945a565c8bf02931677131b43f930493 Mon Sep 17 00:00:00 2001 From: Andreas Grois Date: Sat, 27 Jan 2024 19:58:39 +0100 Subject: Start working on pipe_chan --- alsa/src/communication/pipe_chan.rs | 81 +++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 alsa/src/communication/pipe_chan.rs (limited to 'alsa/src/communication') diff --git a/alsa/src/communication/pipe_chan.rs b/alsa/src/communication/pipe_chan.rs new file mode 100644 index 0000000..1a671ea --- /dev/null +++ b/alsa/src/communication/pipe_chan.rs @@ -0,0 +1,81 @@ +use std::{ffi::{c_int, c_void}, fmt::Display, error::Error}; +use libc::{read, close, pipe2, O_NONBLOCK, EINTR }; +use errno::{errno, set_errno, Errno}; //Why isn't this in libc?!? + +/// Sends byte data to the corresponding receiver. +pub(crate) struct Sender { + handle : FileHandle, +} +/// Receives byte data from the corresponding sender. +pub(crate) struct Receiver { + handle : FileHandle, +} + +impl Receiver { + pub(crate) fn read_byte(&self) -> Result, ReceiveError> { + set_errno(Errno(0)); + let mut buf : u8 = 0; + let status = unsafe {read(self.handle.get_raw(),&mut buf as *mut u8 as *mut c_void, 1)}; + if status == 0 { + //need to check errno. if a signal interrupted, then there is no error and we just + //retry. + //If no error happened, then the sender has hung up and we return err. + let e = errno(); + if e == Errno(0) { + Err(ReceiveError::SenderHasHungUp) + } else if e.0 == EINTR { + self.read_byte() + } else { + //Not sure what to do + todo!() + } + } + else { + todo!() + } + } +} + +#[derive(Debug, Clone, Copy)] +pub(crate) enum ReceiveError { + SenderHasHungUp +} + +impl Display for ReceiveError{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Read failed, Sender has closed their end of the pipe.") + } +} + +impl Error for ReceiveError {} + +pub(crate) fn create_pipe_chan() -> Result<(Sender, Receiver),()> { + let mut handles : [c_int;2] = [0;2]; + let result = unsafe { pipe2(handles.as_mut_ptr(), O_NONBLOCK) }; + if result == -1 { + Err(()) + } else { + Ok(( + Sender{handle : FileHandle{raw : handles[1]}}, + Receiver{handle : FileHandle{ raw : handles[0]}} + )) + } +} + +struct FileHandle { + raw : c_int, +} + +impl FileHandle { + pub(crate) fn get_raw(&self) -> c_int { + self.raw + } +} + +impl Drop for FileHandle { + fn drop(&mut self) { + unsafe { + close(self.raw); + } + } +} -- cgit v1.2.3