Skip to main content

imsg_session/
lifecycle.rs

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