Skip to content

Commit

Permalink
[darwin] Race when BleConnection stop is called
Browse files Browse the repository at this point in the history
  • Loading branch information
vivien-apple committed Mar 8, 2023
1 parent 32fb896 commit 79ef679
Showing 1 changed file with 62 additions and 36 deletions.
98 changes: 62 additions & 36 deletions src/platform/Darwin/BleConnectionDelegateImpl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <lib/support/logging/CHIPLogging.h>
#include <platform/CHIPDeviceLayer.h>
#include <platform/Darwin/BleConnectionDelegate.h>
#include <platform/LockTracker.h>
#include <setup_payload/SetupPayload.h>

#import "UUIDHelper.h"
Expand All @@ -40,10 +41,10 @@

constexpr uint64_t kScanningWithDiscriminatorTimeoutInSeconds = 60;
constexpr uint64_t kScanningWithoutDiscriminatorTimeoutInSeconds = 120;
constexpr const char * kBleWorkQueueName = "org.csa-iot.matter.framework.ble.workqueue";

@interface BleConnection : NSObject <CBCentralManagerDelegate, CBPeripheralDelegate>

@property (strong, nonatomic) dispatch_queue_t workQueue;
@property (strong, nonatomic) dispatch_queue_t chipWorkQueue;
@property (strong, nonatomic) CBCentralManager * centralManager;
@property (strong, nonatomic) CBPeripheral * peripheral;
Expand All @@ -58,7 +59,8 @@ @interface BleConnection : NSObject <CBCentralManagerDelegate, CBPeripheralDeleg
@property (unsafe_unretained, nonatomic) BleConnectionDelegate::OnConnectionErrorFunct onConnectionError;
@property (unsafe_unretained, nonatomic) chip::Ble::BleLayer * mBleLayer;

- (id)initWithDiscriminator:(const chip::SetupDiscriminator &)deviceDiscriminator;
- (id)initWithQueue:(dispatch_queue_t)queue;
- (id)initWithDiscriminator:(const chip::SetupDiscriminator &)deviceDiscriminator queue:(dispatch_queue_t)queue;
- (void)setBleLayer:(chip::Ble::BleLayer *)bleLayer;
- (void)start;
- (void)stop;
Expand All @@ -72,57 +74,80 @@ - (void)update;
namespace DeviceLayer {
namespace Internal {
BleConnection * ble;
dispatch_queue_t bleWorkQueue;

void BleConnectionDelegateImpl::NewConnection(
Ble::BleLayer * bleLayer, void * appState, const SetupDiscriminator & deviceDiscriminator)
{
assertChipStackLockedByCurrentThread();

ChipLogProgress(Ble, "%s", __FUNCTION__);
if (!bleWorkQueue) {
bleWorkQueue = dispatch_queue_create(kBleWorkQueueName, DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL);
}

dispatch_async(bleWorkQueue, ^{
// If the previous connection delegate was a scan without a discriminator, just reuse it instead of
// creating a brand new connection but update the discriminator and the ble layer members.
if (ble and ![ble hasDiscriminator]) {
[ble setBleLayer:bleLayer];
ble.appState = appState;
ble.onConnectionComplete = OnConnectionComplete;
ble.onConnectionError = OnConnectionError;
[ble updateWithDiscriminator:deviceDiscriminator];
return;
}

// If the previous connection delegate was a scan without a discriminator, just reuse it instead of
// creating a brand new connection but update the discriminator and the ble layer members.
if (ble and ![ble hasDiscriminator]) {
[ble stop];
ble = [[BleConnection alloc] initWithDiscriminator:deviceDiscriminator queue:bleWorkQueue];
[ble setBleLayer:bleLayer];
ble.appState = appState;
ble.onConnectionComplete = OnConnectionComplete;
ble.onConnectionError = OnConnectionError;
[ble updateWithDiscriminator:deviceDiscriminator];
return;
}

CancelConnection();
ble = [[BleConnection alloc] initWithDiscriminator:deviceDiscriminator];
[ble setBleLayer:bleLayer];
ble.appState = appState;
ble.onConnectionComplete = OnConnectionComplete;
ble.onConnectionError = OnConnectionError;
ble.centralManager = [ble.centralManager initWithDelegate:ble queue:ble.workQueue];
ble.centralManager = [ble.centralManager initWithDelegate:ble queue:bleWorkQueue];
});
}

void BleConnectionDelegateImpl::PrepareConnection()
{
ChipLogProgress(Ble, "%s", __FUNCTION__);
assertChipStackLockedByCurrentThread();

// If the previous connection delegate was a scan without a discriminator, just reuse it instead of
// creating a brand new connection but clear the cache and reset the timer.
if (ble and ![ble hasDiscriminator]) {
[ble update];
return;
ChipLogProgress(Ble, "%s", __FUNCTION__);
if (!bleWorkQueue) {
bleWorkQueue = dispatch_queue_create(kBleWorkQueueName, DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL);
}

CancelConnection();
ble = [[BleConnection alloc] init];
ble.onConnectionComplete = OnConnectionComplete;
ble.onConnectionError = OnConnectionError;
ble.centralManager = [ble.centralManager initWithDelegate:ble queue:ble.workQueue];
dispatch_async(bleWorkQueue, ^{
// If the previous connection delegate was a scan without a discriminator, just reuse it instead of
// creating a brand new connection but clear the cache and reset the timer.
if (ble and ![ble hasDiscriminator]) {
[ble update];
return;
}

[ble stop];
ble = [[BleConnection alloc] initWithQueue:bleWorkQueue];
ble.onConnectionComplete = OnConnectionComplete;
ble.onConnectionError = OnConnectionError;
ble.centralManager = [ble.centralManager initWithDelegate:ble queue:bleWorkQueue];
});
}

CHIP_ERROR BleConnectionDelegateImpl::CancelConnection()
{
assertChipStackLockedByCurrentThread();

ChipLogProgress(Ble, "%s", __FUNCTION__);
if (ble) {
if (bleWorkQueue == nil) {
return CHIP_NO_ERROR;
}

dispatch_async(bleWorkQueue, ^{
[ble stop];
ble = nil;
}
});

bleWorkQueue = nil;
return CHIP_NO_ERROR;
}
} // namespace Internal
Expand All @@ -134,15 +159,13 @@ @interface BleConnection ()

@implementation BleConnection

- (id)init
- (id)initWithQueue:(dispatch_queue_t)queue
{
self = [super init];
if (self) {
self.shortServiceUUID = [UUIDHelper GetShortestServiceUUID:&chip::Ble::CHIP_BLE_SVC_ID];
_workQueue
= dispatch_queue_create("org.csa-iot.matter.framework.ble.workqueue", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL);
_chipWorkQueue = chip::DeviceLayer::PlatformMgrImpl().GetWorkQueue();
_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _workQueue);
_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
_centralManager = [CBCentralManager alloc];
_found = false;
_cachedPeripherals = [[NSMutableDictionary alloc] init];
Expand All @@ -159,9 +182,9 @@ - (id)init
return self;
}

- (id)initWithDiscriminator:(const chip::SetupDiscriminator &)deviceDiscriminator
- (id)initWithDiscriminator:(const chip::SetupDiscriminator &)deviceDiscriminator queue:(dispatch_queue_t)queue
{
self = [self init];
self = [self initWithQueue:queue];
if (self) {
_deviceDiscriminator = deviceDiscriminator;
_hasDeviceDiscriminator = true;
Expand Down Expand Up @@ -460,7 +483,10 @@ - (void)disconnect
return;
}

_mBleLayer->CloseAllBleConnections();
dispatch_sync(_chipWorkQueue, ^{
_mBleLayer->CloseAllBleConnections();
});

_peripheral = nil;
}

Expand Down

0 comments on commit 79ef679

Please sign in to comment.