Skip to content

Commit

Permalink
l2cap: add non-blocking read and write APIs.
Browse files Browse the repository at this point in the history
  • Loading branch information
Dirbaio committed Mar 25, 2024
1 parent 020bf83 commit a6e0678
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 3 deletions.
33 changes: 30 additions & 3 deletions src/android/l2cap_channel.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::sync::Arc;
use std::{fmt, slice, thread};

use async_channel::{Receiver, Sender};
use async_channel::{Receiver, Sender, TryRecvError, TrySendError};
use java_spaghetti::{ByteArray, Global, Local, PrimitiveArray};
use tracing::{debug, warn};

Expand Down Expand Up @@ -151,7 +151,27 @@ impl L2capChannelReader {
.stream
.recv()
.await
.map_err(|_| Error::new(ErrorKind::ConnectionFailed, None, "L2CAP channel is closed".to_string()))?;
.map_err(|_| Error::new(ErrorKind::ConnectionFailed, None, "channel is closed".to_string()))?;

if packet.len() > buf.len() {
return Err(Error::new(
ErrorKind::InvalidParameter,
None,
"Buffer is too small".to_string(),
));
}

buf[..packet.len()].copy_from_slice(&packet);

Ok(packet.len())
}

#[inline]
pub fn try_read(&mut self, buf: &mut [u8]) -> Result<usize> {
let packet = self.stream.try_recv().map_err(|e| match e {
TryRecvError::Empty => Error::new(ErrorKind::NotReady, None, "no received packet in queue".to_string()),
TryRecvError::Closed => Error::new(ErrorKind::ConnectionFailed, None, "channel is closed".to_string()),
})?;

if packet.len() > buf.len() {
return Err(Error::new(
Expand Down Expand Up @@ -188,7 +208,14 @@ impl L2capChannelWriter {
self.stream
.send(packet.to_vec())
.await
.map_err(|_| Error::new(ErrorKind::ConnectionFailed, None, "L2CAP channel is closed".to_string()))
.map_err(|_| Error::new(ErrorKind::ConnectionFailed, None, "channel is closed".to_string()))
}

pub fn try_write(&mut self, packet: &[u8]) -> Result<()> {
self.stream.try_send(packet.to_vec()).map_err(|e| match e {
TrySendError::Closed(_) => Error::new(ErrorKind::ConnectionFailed, None, "channel is closed".to_string()),
TrySendError::Full(_) => Error::new(ErrorKind::NotReady, None, "No buffer space for write".to_string()),
})
}

pub async fn close(&mut self) -> Result<()> {
Expand Down
8 changes: 8 additions & 0 deletions src/bluer/l2cap_channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ impl L2capChannelReader {
todo!()
}

pub fn try_read(&mut self, buf: &mut [u8]) -> Result<usize> {
todo!()
}

pub async fn close(&mut self) -> Result<()> {
todo!()
}
Expand All @@ -32,6 +36,10 @@ impl L2capChannelWriter {
todo!()
}

pub fn try_write(&mut self, packet: &[u8]) -> Result<()> {
todo!()
}

pub async fn close(&mut self) -> Result<()> {
todo!()
}
Expand Down
8 changes: 8 additions & 0 deletions src/corebluetooth/l2cap_channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ impl L2capChannelReader {
todo!()
}

pub fn try_read(&mut self, buf: &mut [u8]) -> Result<usize> {
todo!()
}

pub async fn close(&mut self) -> Result<()> {
todo!()
}
Expand All @@ -32,6 +36,10 @@ impl L2capChannelWriter {
todo!()
}

pub fn try_write(&mut self, packet: &[u8]) -> Result<()> {
todo!()
}

pub async fn close(&mut self) -> Result<()> {
todo!()
}
Expand Down
20 changes: 20 additions & 0 deletions src/l2cap_channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ impl L2capChannelReader {
self.reader.read(buf).await
}

/// Try reading a packet from the L2CAP channel.
///
/// The packet is written to the start of `buf`, and the packet length is returned.
///
/// If no packet is immediately available for reading, this returns an error with kind `NotReady`.
#[inline]
pub fn try_read(&mut self, buf: &mut [u8]) -> Result<usize> {
self.reader.try_read(buf)
}

/// Close the L2CAP channel.
///
/// This closes the entire channel, not just the read half.
Expand All @@ -76,11 +86,21 @@ impl L2capChannelReader {

impl L2capChannelWriter {
/// Write a packet to the L2CAP channel.
///
/// If the buffer is full, this will wait until there's buffer space for the packet.
#[inline]
pub async fn write(&mut self, packet: &[u8]) -> Result<()> {
self.writer.write(packet).await
}

/// Try writing a packet to the L2CAP channel.
///
/// If there's no buffer space, this returns an error with kind `NotReady`.
#[inline]
pub fn try_write(&mut self, packet: &[u8]) -> Result<()> {
self.writer.try_write(packet)
}

/// Close the L2CAP channel.
///
/// This closes the entire channel, not just the write half.
Expand Down
8 changes: 8 additions & 0 deletions src/windows/l2cap_channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ impl L2capChannelReader {
todo!()
}

pub fn try_read(&mut self, buf: &mut [u8]) -> Result<usize> {
todo!()
}

pub async fn close(&mut self) -> Result<()> {
todo!()
}
Expand All @@ -32,6 +36,10 @@ impl L2capChannelWriter {
todo!()
}

pub fn try_write(&mut self, packet: &[u8]) -> Result<()> {
todo!()
}

pub async fn close(&mut self) -> Result<()> {
todo!()
}
Expand Down

0 comments on commit a6e0678

Please sign in to comment.