Skip to main content

imsg_session/
lifecycle.rs

1//! Connection lifecycle: SDP lookup, RFCOMM connect, OBEX session establishment and teardown.
2
3use std::time::Duration;
4
5use map_core::client::MapClient;
6use pbap_core::client::PbapClient;
7use tokio::io::{AsyncRead, AsyncWrite};
8use transport::rfcomm::DEFAULT_BT_CONNECTED_GATE;
9
10use crate::SessionError;
11
12/// OBEX CONNECT + enable MAP notifications. Caller must hold the returned client — iOS drops
13/// notification registration on OBEX DISCONNECT.
14///
15/// # Errors
16///
17/// Returns [`SessionError::Map`] on OBEX protocol error or server refusal.
18pub async fn establish_map_session<T: AsyncRead + AsyncWrite + Unpin>(
19    stream: T,
20) -> Result<MapClient<T>, SessionError> {
21    let mut client = MapClient::connect(stream).await.inspect_err(|e| {
22        tracing::warn!("MAP session: OBEX CONNECT failed: {e}");
23    })?;
24    tracing::debug!("MAP session: OBEX CONNECT ok, registering notifications");
25    client.set_notification_registration(true).await.inspect_err(|e| {
26        tracing::warn!("MAP session: notification registration failed: {e}");
27    })?;
28    tracing::debug!("MAP session: notification registration ok");
29    Ok(client)
30}
31
32/// RFCOMM connect to `addr`:`channel` (gating on `BT_CONNECTED` up to `bt_gate`) then
33/// [`establish_map_session`].
34///
35/// # Errors
36///
37/// Returns [`SessionError::Transport`] on RFCOMM failure or `BT_CONNECTED` timeout,
38/// [`SessionError::Map`] on OBEX failure.
39pub async fn connect_map(
40    addr: bluer::Address,
41    channel: u8,
42    bt_gate: Duration,
43) -> Result<MapClient<bluer::rfcomm::Stream>, SessionError> {
44    let stream = transport::rfcomm::connect(addr, channel, bt_gate).await?;
45    establish_map_session(stream).await
46}
47
48/// RFCOMM connect to `addr`:`channel` then PBAP OBEX CONNECT.
49///
50/// # Errors
51///
52/// Returns [`SessionError::Transport`] on RFCOMM failure, [`SessionError::Pbap`] on OBEX failure.
53pub async fn connect_pbap(
54    addr: bluer::Address,
55    channel: u8,
56) -> Result<PbapClient<bluer::rfcomm::Stream>, SessionError> {
57    let stream = transport::rfcomm::connect(addr, channel, DEFAULT_BT_CONNECTED_GATE).await?;
58    let client = PbapClient::connect(stream).await?;
59    Ok(client)
60}