From c66bb18ec585e40294588b75e922410e7eb5d8bc Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Mon, 14 Nov 2016 16:50:09 +0100 Subject: LE peripheral manager - warn about value length limit (iOS) Apparently, it cannot exceed the 512-octets limit on iOS. Also, warn about notifications - the value is truncated for a connected peripheral, we are limited by a central.maximumUpdateValueLength. Change-Id: Ia3d09fe0306a2514cf2c6f391cc57e6d300b75fd Reviewed-by: Alex Blasche --- src/bluetooth/osx/osxbtperipheralmanager.mm | 32 ++++++++++++++++++++++++++-- src/bluetooth/osx/osxbtperipheralmanager_p.h | 1 + src/bluetooth/osx/osxbtutility.mm | 2 ++ src/bluetooth/osx/osxbtutility_p.h | 1 + 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/bluetooth/osx/osxbtperipheralmanager.mm b/src/bluetooth/osx/osxbtperipheralmanager.mm index 03b95667..9c443cf6 100644 --- a/src/bluetooth/osx/osxbtperipheralmanager.mm +++ b/src/bluetooth/osx/osxbtperipheralmanager.mm @@ -187,6 +187,7 @@ bool qt_validate_value_range(const QLowEnergyCharacteristicData &data) state = PeripheralState::idle; nextServiceToAdd = {}; connectedCentrals.reset([[NSMutableSet alloc] init]); + maxNotificationValueLength = std::numeric_limits::max(); } return self; @@ -353,8 +354,13 @@ bool qt_validate_value_range(const QLowEnergyCharacteristicData &data) } const auto & range = valueRanges[charHandle]; - if (value.size() < int(range.first) || value.size() > int(range.second)) { - qCWarning(QT_BT_OSX) << "ignoring value of invalid length" << value.count(); + if (value.size() < int(range.first) || value.size() > int(range.second) +#ifdef Q_OS_IOS + || value.size() > OSXBluetooth::maxValueLength) { +#else + ) { +#endif + qCWarning(QT_BT_OSX) << "ignoring value of invalid length" << value.size(); return; } @@ -630,6 +636,12 @@ bool qt_validate_value_range(const QLowEnergyCharacteristicData &data) while (updateQueue.size()) { const auto &request = updateQueue.front(); if (charMap.contains(request.charHandle)) { + if ([connectedCentrals count] + && maxNotificationValueLength < [request.value length]) { + qCWarning(QT_BT_OSX) << "value of length" << [request.value length] + << "will possibly be truncated to" + << maxNotificationValueLength; + } const BOOL res = [manager updateValue:request.value forCharacteristic:static_cast(charMap[request.charHandle]) onSubscribedCentrals:nil]; @@ -655,6 +667,9 @@ bool qt_validate_value_range(const QLowEnergyCharacteristicData &data) return; } + maxNotificationValueLength = std::min(maxNotificationValueLength, + central.maximumUpdateValueLength); + QT_BT_MAC_AUTORELEASEPOOL if (state == PeripheralState::advertising) { @@ -683,6 +698,9 @@ bool qt_validate_value_range(const QLowEnergyCharacteristicData &data) state = PeripheralState::idle; emit notifier->disconnected(); } + + if (![connectedCentrals count]) + maxNotificationValueLength = std::numeric_limits::max(); } - (CBService *)findIncludedService:(const QBluetoothUuid &)qtUUID @@ -749,6 +767,16 @@ bool qt_validate_value_range(const QLowEnergyCharacteristicData &data) continue; } +#ifdef Q_OS_IOS + if (ch.value().length() > OSXBluetooth::maxValueLength) { + qCWarning(QT_BT_OSX) << "addCharacteristicsAndDescritptors: " + "value exceeds the maximal permitted " + "value length (" << OSXBluetooth::maxValueLength + << "octets) on the platform"; + continue; + } +#endif + const auto cbChar(create_characteristic(ch)); if (!cbChar) { qCWarning(QT_BT_OSX) << "addCharacteristicsAndDescritptors: " diff --git a/src/bluetooth/osx/osxbtperipheralmanager_p.h b/src/bluetooth/osx/osxbtperipheralmanager_p.h index b6021fb8..3fee7537 100644 --- a/src/bluetooth/osx/osxbtperipheralmanager_p.h +++ b/src/bluetooth/osx/osxbtperipheralmanager_p.h @@ -137,6 +137,7 @@ using ValueRange = QPair; ObjCScopedPointer connectedCentrals; PeripheralState state; + NSUInteger maxNotificationValueLength; } - (id)initWith:(LECBManagerNotifier *)notifier; diff --git a/src/bluetooth/osx/osxbtutility.mm b/src/bluetooth/osx/osxbtutility.mm index 139ccc54..1508c89f 100644 --- a/src/bluetooth/osx/osxbtutility.mm +++ b/src/bluetooth/osx/osxbtutility.mm @@ -72,6 +72,8 @@ Q_LOGGING_CATEGORY(QT_BT_OSX, "qt.bluetooth.ios") namespace OSXBluetooth { const int defaultLEScanTimeoutMS = 25000; +// We use it only on iOS for now: +const int maxValueLength = 512; QString qt_address(NSString *address) { diff --git a/src/bluetooth/osx/osxbtutility_p.h b/src/bluetooth/osx/osxbtutility_p.h index 3c0e05e7..148ebc0b 100644 --- a/src/bluetooth/osx/osxbtutility_p.h +++ b/src/bluetooth/osx/osxbtutility_p.h @@ -304,6 +304,7 @@ ObjCStrongReference mutable_data_from_bytearray(const QByteArray dispatch_queue_t qt_LE_queue(); extern const int defaultLEScanTimeoutMS; +extern const int maxValueLength; } // namespace OSXBluetooth -- cgit v1.2.3