Commit a41a84b5 authored by Adam Langley's avatar Adam Langley Committed by Commit Bot

Also need to account for GATT overhead on writes.

r754176 was incomplete: it should have trimmed the MTU for writes from
the phone was well as the advertised MTU.

BUG=1002262

Change-Id: I688f86c90fe160014cbcf9cef7ea0d119da7725e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2129886
Auto-Submit: Adam Langley <agl@chromium.org>
Commit-Queue: Martin Kreichgauer <martinkr@google.com>
Reviewed-by: default avatarMartin Kreichgauer <martinkr@google.com>
Cr-Commit-Position: refs/heads/master@{#755000}
parent 6dd70d30
...@@ -73,6 +73,9 @@ class BLEHandler extends BluetoothGattServerCallback implements Closeable { ...@@ -73,6 +73,9 @@ class BLEHandler extends BluetoothGattServerCallback implements Closeable {
private static final String STATE_FILE_NAME = "cablev2_authenticator"; private static final String STATE_FILE_NAME = "cablev2_authenticator";
private static final String STATE_VALUE_NAME = "keys"; private static final String STATE_VALUE_NAME = "keys";
// The (G)ATT op-code and attribute handle take three bytes.
private static final int GATT_MTU_OVERHEAD = 3;
/** /**
* The pending fragments to send to each client. If present, the value is * The pending fragments to send to each client. If present, the value is
* never an empty array. * never an empty array.
...@@ -173,9 +176,19 @@ class BLEHandler extends BluetoothGattServerCallback implements Closeable { ...@@ -173,9 +176,19 @@ class BLEHandler extends BluetoothGattServerCallback implements Closeable {
@Override @Override
public void onMtuChanged(BluetoothDevice device, int mtu) { public void onMtuChanged(BluetoothDevice device, int mtu) {
Long client = addressToLong(device.getAddress()); Long client = addressToLong(device.getAddress());
// At least six bytes is required: three bytes of GATT overhead and
// three bytes of CTAP2 framing. If the requested MTU is less than
// this, try six bytes anyway. The operations will probably fail but
// there's nothing we can do about it.
if (mtu < 6) {
mtu = 6;
}
int clientMTU = mtu - GATT_MTU_OVERHEAD;
mTaskRunner.postTask(() -> { mTaskRunner.postTask(() -> {
mKnownMtus.put(client, mtu); mKnownMtus.put(client, clientMTU);
BLEHandlerJni.get().recordClientMtu(client, mtu); BLEHandlerJni.get().recordClientMtu(client, clientMTU);
}); });
} }
...@@ -195,17 +208,10 @@ class BLEHandler extends BluetoothGattServerCallback implements Closeable { ...@@ -195,17 +208,10 @@ class BLEHandler extends BluetoothGattServerCallback implements Closeable {
mTaskRunner.postTask(() -> { mTaskRunner.postTask(() -> {
Integer mtu = mKnownMtus.get(client); Integer mtu = mKnownMtus.get(client);
if (mtu == null) { if (mtu == null) {
// If no MTU is negotiated, the GATT default is just 23 bytes. // If no MTU is negotiated, the GATT default is just 23
mtu = 23; // bytes. Subtract three bytes of GATT overhead.
} mtu = 23 - GATT_MTU_OVERHEAD;
if (mtu < 4) {
Log.i(TAG, "MTU unusably small");
mServer.sendResponse(
device, requestId, BluetoothGatt.GATT_FAILURE, 0, null);
return;
} }
// The (G)ATT op-code and attribute handle take three bytes.
mtu -= 3;
byte[] mtuBytes = {(byte) (mtu >> 8), (byte) (mtu & 0xff)}; byte[] mtuBytes = {(byte) (mtu >> 8), (byte) (mtu & 0xff)};
mServer.sendResponse( mServer.sendResponse(
device, requestId, BluetoothGatt.GATT_SUCCESS, 0, mtuBytes); device, requestId, BluetoothGatt.GATT_SUCCESS, 0, mtuBytes);
......
...@@ -754,11 +754,15 @@ class CableInterface : public Client::Delegate { ...@@ -754,11 +754,15 @@ class CableInterface : public Client::Delegate {
const JavaParamRef<jbyteArray>& data) { const JavaParamRef<jbyteArray>& data) {
auto it = clients_.find(client_addr); auto it = clients_.find(client_addr);
if (it == clients_.end()) { if (it == clients_.end()) {
DCHECK(known_mtus_.find(client_addr) != known_mtus_.end()); // If no MTU is negotiated, the GATT default is just 23 bytes. Subtract
uint16_t mtu = known_mtus_[client_addr]; // three bytes of GATT overhead.
if (mtu == 0) { static constexpr uint16_t kDefaultMTU = 23 - 3;
mtu = 512; // TODO: once we only handle a single client, the Java code can ensure
} // that an MTU has always been set and this code wont need to know a
// default.
const auto& mtu_it = known_mtus_.find(client_addr);
const uint16_t mtu =
mtu_it == known_mtus_.end() ? kDefaultMTU : mtu_it->second;
it = clients_ it = clients_
.emplace(client_addr, .emplace(client_addr,
new Client(client_addr, mtu, &auth_state_, this)) new Client(client_addr, mtu, &auth_state_, this))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment