Skip to content

Commit

Permalink
fix: use async version of send for gatt replies
Browse files Browse the repository at this point in the history
* Print warning if outbound channel is full on reply drop
  • Loading branch information
lulf committed Jan 29, 2025
1 parent 5a33701 commit b1671f1
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 9 deletions.
31 changes: 23 additions & 8 deletions examples/apps/src/ble_bas_peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,30 @@ async fn gatt_events_task(server: &Server<'_>, conn: &Connection<'_>) -> Result<
// the protocol details
match data.process(server).await {
// Server processing emits
Ok(Some(GattEvent::Read(event))) => {
if event.handle() == level.handle {
let value = server.get(&level);
info!("[gatt] Read Event to Level Characteristic: {:?}", value);
Ok(Some(event)) => {
match &event {
GattEvent::Read(event) => {
if event.handle() == level.handle {
let value = server.get(&level);
info!("[gatt] Read Event to Level Characteristic: {:?}", value);
}
}
GattEvent::Write(event) => {
if event.handle() == level.handle {
info!("[gatt] Write Event to Level Characteristic: {:?}", event.data());
}
}
}
}
Ok(Some(GattEvent::Write(event))) => {
if event.handle() == level.handle {
info!("[gatt] Write Event to Level Characteristic: {:?}", event.data());

// This step is also performed at drop(), but writing it explicitly is necessary
// in order to ensure reply is sent.
match event.accept() {
Ok(reply) => {
reply.send().await;
}
Err(e) => {
warn!("[gatt] error sending response: {:?}", e);
}
}
}
Ok(_) => {}
Expand Down
22 changes: 21 additions & 1 deletion host/src/gatt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,24 @@ pub enum GattEvent<'stack, 'server> {
Write(WriteEvent<'stack, 'server>),
}

impl<'stack, 'server> GattEvent<'stack, 'server> {
/// Accept the event, making it processed by the server.
pub fn accept(self) -> Result<Reply<'stack>, Error> {
match self {
Self::Read(e) => e.accept(),
Self::Write(e) => e.accept(),
}
}

/// Reject the event with the provided error code, it will not be processed by the attribute server.
pub fn reject(self, err: AttErrorCode) -> Result<Reply<'stack>, Error> {
match self {
Self::Read(e) => e.reject(err),
Self::Write(e) => e.reject(err),
}
}
}

/// An event returned while processing GATT requests.
pub struct ReadEvent<'stack, 'server> {
value_handle: u16,
Expand Down Expand Up @@ -290,7 +308,9 @@ impl<'stack> Reply<'stack> {
impl Drop for Reply<'_> {
fn drop(&mut self) {
if let Some(pdu) = self.pdu.take() {
let _ = self.connection.try_send(pdu);
if self.connection.try_send(pdu).is_err() {
warn!("[gatt] error sending reply (outbound buffer full)");
}
}
}
}
Expand Down

0 comments on commit b1671f1

Please sign in to comment.