Tested on Debian 12, Linux 6.1.0-32-amd64, BlueZ version 5.66. BlueR was at commit 45d0837.
connect inconsistently reports "connection refused", causing errors in later reads and writes. In testing, errors were successfully reported 0-5% of the time on L2CAP streams and L2CAP seqpacket connections, and 30-50% of the time on RFCOMM connections.
The "invalid argument" error is not affected.
I encountered this bug while trying to diagnose #163, hence the similar example.
Examples
I ran these examples with an Android phone, which was already paired and connected over audio. I chose channels which were not open to deliberately trigger an error.
L2CAP stream example
use bluer::AddressType;
use bluer::l2cap::{Socket, SocketAddr};
use tokio::io::AsyncWriteExt;
#[tokio::main]
async fn main() {
let address = SocketAddr::new(
"50:13:1D:XX:XX:XX".parse().unwrap(),
AddressType::BrEdr,
0x13,
);
let socket = Socket::new_stream().expect("new");
println!("Connecting");
let mut connection = socket.connect(address).await.expect("connect");
println!("Connected");
println!("Writing data");
connection.write(&[0x00]).await.expect("write");
println!("Written");
}
L2CAP seqpacket example
use bluer::AddressType;
use bluer::l2cap::{Socket, SocketAddr};
#[tokio::main]
async fn main() {
let address = SocketAddr::new(
"50:13:1D:XX:XX:XX".parse().unwrap(),
AddressType::BrEdr,
0x13,
);
let socket = Socket::new_seq_packet().expect("new");
println!("Connecting");
let connection = socket.connect(address).await.expect("connect");
println!("Connected");
println!("Writing data");
connection.send(&[0x00]).await.expect("send");
println!("Written");
}
RFCOMM example
use bluer::rfcomm::{Socket, SocketAddr};
use tokio::io::AsyncWriteExt;
#[tokio::main]
async fn main() {
let address = SocketAddr::new(
"50:13:1D:XX:XX:XX".parse().unwrap(),
0x0A,
);
let socket = Socket::new().expect("new");
println!("Connecting");
let mut connection = socket.connect(address).await.expect("connect");
println!("Connected");
println!("Writing data");
connection.write(&[0x00]).await.expect("write");
println!("Written");
}
Output
Actual output is
Connecting
Connected
Writing data
thread 'main' panicked at src/main.rs:20:37:
send: Os { code: 107, kind: NotConnected, message: "Transport endpoint is not connected" }
Expected:
Connecting
thread 'main' panicked at src/main.rs:16:56:
connect: Os { code: 111, kind: ConnectionRefused, message: "Connection refused" }
Suspected causes
In testing, getsockopt(socket, SOL_SOCKET, SO_ERROR) would usually return 0 if the socket was not selected/polled for readiness, as if the connection had completed. This was true in Rust and Python.
The problem doesn't occur if I use Mio for polling, instead of Tokio. I suspect that Tokio's AsyncFd isn't using the OS's select or poll to determine readiness, causing false positives, but I'm unsure. There might be other sources of false positives.
Tested on Debian 12, Linux 6.1.0-32-amd64, BlueZ version 5.66. BlueR was at commit 45d0837.
connectinconsistently reports "connection refused", causing errors in later reads and writes. In testing, errors were successfully reported 0-5% of the time on L2CAP streams and L2CAP seqpacket connections, and 30-50% of the time on RFCOMM connections.The "invalid argument" error is not affected.
I encountered this bug while trying to diagnose #163, hence the similar example.
Examples
I ran these examples with an Android phone, which was already paired and connected over audio. I chose channels which were not open to deliberately trigger an error.
L2CAP stream example
L2CAP seqpacket example
RFCOMM example
Output
Actual output is
Expected:
Suspected causes
In testing,
getsockopt(socket, SOL_SOCKET, SO_ERROR)would usually return 0 if the socket was not selected/polled for readiness, as if the connection had completed. This was true in Rust and Python.The problem doesn't occur if I use Mio for polling, instead of Tokio. I suspect that Tokio's
AsyncFdisn't using the OS'sselectorpollto determine readiness, causing false positives, but I'm unsure. There might be other sources of false positives.