Skip to content

L2CAP connection fails if there's no delay after connect #163

@lmore377

Description

@lmore377

I'm trying to connect to the L2CAP channel for AVRCP/OBEX image transfer on an iOS device. I was having an issue where I would get the error { kind: Internal(Io(NotConnected)), message: "Transport endpoint is not connected (os error 107)" } when trying to send data unless I ran my code repeatedly, and even then it would only work about 10% of the time. Eventually I figured out that if I add a sleep/delay after the connect function, my code would start working fine. Am I doing something wrong or is there a bug?

Here's my Rust code:

use bluer::l2cap::{Opts, Socket, SocketAddr};
use bluer::AddressType;
use tokio::io::AsyncWriteExt;
use std::{thread, time::Duration};

const OBEX_HELLO: [u8; 26] = [
    0x80, 0x00, 0x1a, 0x15, 0x00, 0x06, 0x9b, 0x46, 0x00, 0x13, 0x71, 0x63, 0xdd, 0x54, 0x4a, 0x7e,
    0x11, 0xe2, 0xb4, 0x7c, 0x00, 0x50, 0xc2, 0x49, 0x00, 0x48,
];

fn create_l2cap_opts() -> Opts {
    let mut opts = Opts::default();
    opts.omtu = 672;
    opts.imtu = 1024;
    opts.flush_to = 65535;
    opts.mode = 3;
    opts.fcs = 1;
    opts.max_tx = 16;
    opts.txwin_size = 63;

    opts
}

#[tokio::main]
async fn main() -> bluer::Result<()> {
    let session = bluer::Session::new().await?;
    let adapter = session.adapter("hci0")?;
    adapter.set_powered(true).await?;
    let target_sa = SocketAddr::new(
        "B8:B2:F8:XX:XX:XX".parse().unwrap(), // MAC Obfuscated
        AddressType::BrEdr,
        0x1007,
    );

    println!("Connecting to {:?}", &target_sa);
    let socket = Socket::new_stream()?;
    socket.set_l2cap_opts(&create_l2cap_opts())?;

    println!("Before connection: {:?}", socket.l2cap_opts()?);
    let mut stream = socket.connect(target_sa).await.expect("connection failed");
    thread::sleep(Duration::from_millis(1500)); // If this is removed, connection fails most of the time
    println!("After connection: {:?}", stream.as_ref().l2cap_opts()?);

    stream.write_all(&OBEX_HELLO).await?;
    println!("Sent successfully");

    Ok(())
}

And some Python/PyBlueZ code with the same functionality for reference. In this code, I don't need the delay:

Python code
import bluetooth

bt_addr = "B8:B2:F8:XX:XX:XX" # MAC Obfuscated
psm = 0x1007
obexConnReq = bytes.fromhex("80001a1500069b4600137163dd544a7e11e2b47c0050c2490048")

sock = bluetooth.BluetoothSocket(bluetooth.L2CAP)
sock.set_l2cap_options([672, 1024, 65535, 3, 1, 16, 63])

print(f"Before connection: {sock.get_l2cap_options()}")

print(f"Connecting to {bt_addr} on PSM {psm}")
sock.connect((bt_addr, psm))
print(f"Connected to {bt_addr} on PSM {psm}.")

print(f"After connection: {sock.get_l2cap_options()}")

sock.send(obexConnReq)

print("Sent successfully")

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions