Skip to content

Inconsistency in handling Bluetooth addresses #132099

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
serhiy-storchaka opened this issue Apr 4, 2025 · 1 comment
Closed

Inconsistency in handling Bluetooth addresses #132099

serhiy-storchaka opened this issue Apr 4, 2025 · 1 comment
Assignees
Labels
docs Documentation in the Doc dir type-bug An unexpected behavior, bug, or error

Comments

@serhiy-storchaka
Copy link
Member

serhiy-storchaka commented Apr 4, 2025

Bug report

  1. The format accepted by BTPROTO_HCI protocol is incorrectly documented.
    • it accepts a bytes object bdaddr, not a tuple.
    • bdaddr is a bytes object, not a string.
  2. Some protocols accept bdaddr as a string, others accept it as a bytes object. getsockname() returns it as a string or a bytes object, and this is not always consistent with the accepted type.
  3. getsockname() not always return an address in the acceptable format. It returns device_id when the acceptable format is a tuple (device_id,), can return a string when the acceptable format is a bytes object.

First problem should be solved by updating the documentation.

For second problem, I propose to make both string and bytes be accepted as a Bluetooth address. Also, if a 1-tuple is accepted, then its element should be accepted, and if bdaddr is accepted, then a 1-tuple (bdaddr,) should be accepted.

The third problem cannot be resolved in backward compatible way. The solution for the second problem formally fixes incompatibility between input and output formats, but formats are still inconsistent between protocols. And after adding support for hci_channel (see #70145), the type of the getsockname() result will depend on the hci_channel value.

Linked PRs

@serhiy-storchaka serhiy-storchaka added docs Documentation in the Doc dir type-bug An unexpected behavior, bug, or error labels Apr 4, 2025
@serhiy-storchaka serhiy-storchaka self-assigned this Apr 4, 2025
serhiy-storchaka added a commit to serhiy-storchaka/cpython that referenced this issue Apr 5, 2025
serhiy-storchaka added a commit to serhiy-storchaka/cpython that referenced this issue Apr 13, 2025
serhiy-storchaka added a commit to serhiy-storchaka/cpython that referenced this issue Apr 13, 2025
Now all protocols always accept the Bluetooth address as string and
getsockname() always returns the Bluetooth address as string.

* BTPROTO_SCO now accepts not only bytes, but str.
* BTPROTO_SCO now checks address for embedded null.
* On *BSD, BTPROTO_HCI now accepts str instead of bytes.
* On FreeBSD, getsockname() for BTPROTO_HCI now returns str instead of bytes.
* On NetBSD and DragonFly BDS, BTPROTO_HCI now checks address for embedded null.
serhiy-storchaka added a commit to serhiy-storchaka/cpython that referenced this issue Apr 13, 2025
Now all protocols always accept the Bluetooth address as string and
getsockname() always returns the Bluetooth address as string.

* BTPROTO_SCO now accepts not only bytes, but str.
* BTPROTO_SCO now checks address for embedded null.
* On *BSD, BTPROTO_HCI now accepts str instead of bytes.
* On FreeBSD, getsockname() for BTPROTO_HCI now returns str instead of bytes.
* On NetBSD and DragonFly BDS, BTPROTO_HCI now checks address for embedded null.
serhiy-storchaka added a commit that referenced this issue Apr 14, 2025
Now all protocols always accept the Bluetooth address as string and
getsockname() always returns the Bluetooth address as string.

* BTPROTO_SCO now accepts not only bytes, but str.
* BTPROTO_SCO now checks address for embedded null.
* On *BSD, BTPROTO_HCI now accepts str instead of bytes.
* On FreeBSD, getsockname() for BTPROTO_HCI now returns str instead of bytes.
* On NetBSD and DragonFly BDS, BTPROTO_HCI now checks address for embedded null.
serhiy-storchaka added a commit to serhiy-storchaka/cpython that referenced this issue Apr 14, 2025
…H-132486)

Now all protocols always accept the Bluetooth address as string and
getsockname() always returns the Bluetooth address as string.

* BTPROTO_SCO now accepts not only bytes, but str.
* BTPROTO_SCO now checks address for embedded null.
* On *BSD, BTPROTO_HCI now accepts str instead of bytes.
* On FreeBSD, getsockname() for BTPROTO_HCI now returns str instead of bytes.
* On NetBSD and DragonFly BDS, BTPROTO_HCI now checks address for embedded null.
(cherry picked from commit 1fc1df8)

Co-authored-by: Serhiy Storchaka <[email protected]>
serhiy-storchaka added a commit that referenced this issue Apr 14, 2025
…H-132497)

Now all protocols always accept the Bluetooth address as string and
getsockname() always returns the Bluetooth address as string.

* BTPROTO_SCO now accepts not only bytes, but str.
* BTPROTO_SCO now checks address for embedded null.
* On *BSD, BTPROTO_HCI now accepts str instead of bytes.
* On FreeBSD, getsockname() for BTPROTO_HCI now returns str instead of bytes.
* On NetBSD and DragonFly BSD, BTPROTO_HCI now checks address for embedded null.
(cherry picked from commit 1fc1df8)
@serhiy-storchaka
Copy link
Member Author

Fortunately, the code was completely broken on *BSD systems, so most of this inconsistencies was shielded by other bugs. We were able to change the accepted and returned types without breaking code even more.

The only inconsistency left is in the BTPROTO_HCI protocol on Linux: accepted address is a tuple, but getsockname() returns device_id as an integer. After adding support of channel in #70145, getsockname() can now return a tuple if channel is not zero. It is still weird that the type of the result depends on the value, but this is for backward compatibility. To make input/output consistent, we mast an integer device_id be accepted as an address.

serhiy-storchaka added a commit to serhiy-storchaka/cpython that referenced this issue Apr 14, 2025
…Linux

Previously only an integer packed in a tuple was accepted, while
getsockname() could return a raw integer.
Now the result of getsockname() is always acceptable as an address.
serhiy-storchaka added a commit that referenced this issue Apr 16, 2025
…H-132525)

Previously only an integer packed in a tuple was accepted, while
getsockname() could return a raw integer.
Now the result of getsockname() is always acceptable as an address.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Documentation in the Doc dir type-bug An unexpected behavior, bug, or error
Projects
Status: Todo
Development

No branches or pull requests

1 participant