aboutsummaryrefslogtreecommitdiff
path: root/alsa/src/communication
diff options
context:
space:
mode:
Diffstat (limited to 'alsa/src/communication')
-rw-r--r--alsa/src/communication/pipe_chan.rs81
1 files changed, 81 insertions, 0 deletions
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<Option<u8>, 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);
+ }
+ }
+}