Add BluetoothRemoteGATTCharacteristic.getMTU()#672
Conversation
Expose the negotiated ATT_MTU for the connection carrying a characteristic via a new getMTU() method, returning the smaller of the local Host's transmit ATT_MTU and the peer's receive ATT_MTU as established by the Exchange MTU procedure. Knowing the MTU lets sites size writeValueWithoutResponse() payloads to fit a single PDU and avoid fragmentation.
I think it has to be there because of the way BlueZ implements it. In theory, other OSes could add support for per-characteristic MTU in the future as well.
Since the actual useful information we want is "what is the max size can I use for write without response", I would use a name inspired from CoreBluetooth instead, e.g. Since most OSes don't actually perform any I/O to get the number (they just return whatever number they currently know), making it a promise seems misleading. I also know from experience with maintaining the Bleak Python library that MTU changes can come late (after connecting and resolving services), particularly on Windows. So it could actually make more sense to make this an event rather than an attribute. Or we just need to document that the value can change, so it should be read every time that it is used rather than caching it in some variable in the user application. |
Hi folks 👋
I've been working on the Chromium implementation for exposing the
negotiated ATT MTU to web pages (crrev.com/c/7879985)
What this adds
A new
getMTU()method onBluetoothRemoteGATTCharacteristic:It resolves with the ATT_MTU negotiated for the connection that carries
the characteristic, i.e. the smaller of the local Host's transmit
ATT_MTU and the peer's receive ATT_MTU, as established by the Exchange
MTU procedure. When no exchange has happened it's the default of 23
octets.
Why I want this
Today there's no way for a site to know how big a single write can be.
The practical pain is
writeValueWithoutResponse(): if you hand it morethan
ATT_MTU - 3bytes, the write either fails or gets silentlychopped depending on the platform, and the page has no way to tell ahead
of time. People end up hard-coding 20 (the old default payload) to be
safe, which leaves a lot of throughput on the table on modern devices
that happily negotiate 247+.
Exposing the MTU lets sites chunk their writes to fit a single PDU and
avoid unnecessary round trips. This has been asked for a few times over
the years (40265040 / 40686244 / 40163619 on the Chromium side).
Open questions
the MTU is really a per-connection property. Happy to move it to
BluetoothRemoteGATTServerif folks feel that's a cleaner home.getMTU()vs anmtuattribute. I went with a method sincethe value is only meaningful while connected and resolving a promise
felt more honest than a sync attribute that can throw/stale, but I'm
not attached to it.
Preview | Diff