[NC] Fix L2CAP Client.

PiperOrigin-RevId: 764691433
This commit is contained in:
Edwin Wu
2025-05-29 05:46:04 -07:00
committed by Copybara-Service
parent 023c4b9b4b
commit be830a5fef
6 changed files with 45 additions and 39 deletions
@@ -42,23 +42,24 @@ typedef void (^GNCRequestDisconnectionHandler)(id<GNCPeripheral> peripheral);
- (instancetype)init NS_UNAVAILABLE;
/**
* Initializes the L2CAP client with a specified peripheral.
* Initializes the L2CAP client with a specified request disconnection handler.
*
* @param peripheral The peripheral instance.
* @param requestDisconnectionHandler Called on a private queue with @c peripheral when the
* connection to the peripheral should be cancelled.
*/
- (instancetype)initWithPeripheral:(id<GNCPeripheral>)peripheral
requestDisconnectionHandler:(GNCRequestDisconnectionHandler)requestDisconnectionHandler;
- (instancetype)initWithRequestDisconnectionHandler:
(GNCRequestDisconnectionHandler)requestDisconnectionHandler;
/**
* Opens a L2CAP channel with the @c PSM.
*
* @param PSM The PSM to use for opening the L2CAP channel.
* @param peripheral The peripheral instance.
* @param completionHandler Called on a private queue with the opened L2CAP stream if successfully
* opened or an error if one has occurred.
*/
- (void)openL2CAPChannelWithPSM:(uint16_t)PSM
peripheral:(id<GNCPeripheral>)peripheral
completionHandler:(GNCOpenL2CAPStreamCompletionHandler)completionHandler;
/** Cancels an active or pending local connection to a peripheral. */
@@ -37,39 +37,41 @@ static char *const kGNCBLEL2CAPClientQueueLabel = "com.google.nearby.GNCBLEL2CAP
GNCBLEL2CAPStream *_l2CAPStream;
}
- (instancetype)initWithPeripheral:(id<GNCPeripheral>)peripheral
requestDisconnectionHandler:(GNCRequestDisconnectionHandler)requestDisconnectionHandler {
return [self initWithPeripheral:peripheral
queue:dispatch_queue_create(kGNCBLEL2CAPClientQueueLabel,
DISPATCH_QUEUE_SERIAL)
requestDisconnectionHandler:requestDisconnectionHandler];
- (instancetype)initWithRequestDisconnectionHandler:
(GNCRequestDisconnectionHandler)requestDisconnectionHandler {
return
[self initWithQueue:dispatch_queue_create(kGNCBLEL2CAPClientQueueLabel, DISPATCH_QUEUE_SERIAL)
requestDisconnectionHandler:requestDisconnectionHandler];
};
// This is private and should only be used for tests. The provided peripheral must call
// delegate methods on the main queue.
- (instancetype)initWithPeripheral:(id<GNCPeripheral>)peripheral
queue:(nullable dispatch_queue_t)queue
requestDisconnectionHandler:(GNCRequestDisconnectionHandler)requestDisconnectionHandler {
- (instancetype)initWithQueue:(nullable dispatch_queue_t)queue
requestDisconnectionHandler:(GNCRequestDisconnectionHandler)requestDisconnectionHandler {
self = [super init];
if (self) {
_queue = queue ?: dispatch_get_main_queue();
_peripheral = peripheral;
_peripheral.peripheralDelegate = self;
_requestDisconnectionHandler = requestDisconnectionHandler;
}
return self;
};
- (void)openL2CAPChannelWithPSM:(uint16_t)PSM
peripheral:(id<GNCPeripheral>)peripheral
completionHandler:(GNCOpenL2CAPStreamCompletionHandler)completionHandler {
GTMLoggerInfo(@"[NEARBY] openL2CAPChannelWithPSM = %d", PSM);
_peripheral = peripheral;
_peripheral.peripheralDelegate = self;
_completionHandler = [completionHandler copy];
[_peripheral openL2CAPChannel:(CBL2CAPPSM)PSM];
}
- (void)disconnect {
dispatch_async(_queue, ^{
_requestDisconnectionHandler(_peripheral);
id<GNCPeripheral> localPeripheral = _peripheral;
_requestDisconnectionHandler(localPeripheral);
_peripheral = nil;
_peripheral.peripheralDelegate = nil;
});
}
@@ -130,15 +132,11 @@ static char *const kGNCBLEL2CAPClientQueueLabel = "com.google.nearby.GNCBLEL2CAP
#pragma mark Private
- (void)shutDown {
_peripheral = nil;
_peripheral.peripheralDelegate = nil;
}
- (void)closeL2CAPChannel {
[_l2CAPStream tearDown];
_l2CAPStream = nil;
_l2CAPChannel = nil;
[self disconnect];
}
@end
@@ -277,10 +277,12 @@ static GNCBLEL2CAPServer *_Nonnull CreateL2CapServer(
return;
}
if (!strongSelf->_l2capClient) {
strongSelf->_l2capClient =
[[GNCBLEL2CAPClient alloc] initWithPeripheral:remotePeripheral
requestDisconnectionHandler:^(id<GNCPeripheral> _Nonnull peripheral){
}];
strongSelf->_l2capClient = [[GNCBLEL2CAPClient alloc]
initWithRequestDisconnectionHandler:^(id<GNCPeripheral> _Nonnull peripheral) {
dispatch_async(_queue, ^{
[_centralManager cancelPeripheralConnection:remotePeripheral];
});
}];
}
strongSelf->_l2capStreamCompletionHandlers[remotePeripheral.identifier] = completionHandler;
strongSelf->_l2capPSM = psm;
@@ -412,6 +414,7 @@ static GNCBLEL2CAPServer *_Nonnull CreateL2CapServer(
[_l2capClient
openL2CAPChannelWithPSM:_l2capPSM
peripheral:remotePeripheral
completionHandler:^(GNCBLEL2CAPStream *_Nullable stream, NSError *_Nullable error) {
__typeof__(self) strongSelf = weakSelf;
if (!strongSelf) {
@@ -23,18 +23,16 @@ NS_ASSUME_NONNULL_BEGIN
@interface GNCBLEL2CAPClient (Testing)
/**
* Creates a L2CAP client with a provided peripheral.
* Initializes the L2CAP client with a provided queue and request disconnection handler.
*
* This is only exposed for testing and can be used to inject a fake peripheral.
*
* @param peripheral The peripheral instance.
* @param queue The queue to run on, this must match the queue that the peripheral's delegate is
* running on. Defaults to the main queue when @c nil.
* @param requestDisconnectionHandler Called on a private queue with @c peripheral when the
* connection to the peripheral should be cancelled.
*/
-(instancetype)initWithPeripheral:(id<GNCPeripheral>)peripheral
queue:(nullable dispatch_queue_t)queue
-(instancetype)initWithQueue:(nullable dispatch_queue_t)queue
requestDisconnectionHandler:(GNCRequestDisconnectionHandler)requestDisconnectionHandler;
@end
@@ -36,12 +36,11 @@
[super setUp];
self.fakePeripheral = [[GNCFakePeripheral alloc] init];
self.l2capClient =
[[GNCBLEL2CAPClient alloc] initWithPeripheral:self.fakePeripheral
queue:nil
requestDisconnectionHandler:^(id<GNCPeripheral> _Nonnull peripheral) {
XCTAssertNotNil(peripheral);
[self.requestDisconnectionHandlerExpectation fulfill];
}];
[[GNCBLEL2CAPClient alloc] initWithQueue:nil
requestDisconnectionHandler:^(id<GNCPeripheral> _Nonnull peripheral) {
XCTAssertNotNil(peripheral);
[self.requestDisconnectionHandlerExpectation fulfill];
}];
}
- (void)tearDown {
@@ -56,6 +55,7 @@
uint16_t psm = 123;
[self.l2capClient openL2CAPChannelWithPSM:psm
peripheral:self.fakePeripheral
completionHandler:^(GNCBLEL2CAPStream *stream, NSError *error) {
XCTAssertNil(error, @"Error should be nil");
[expectation fulfill];
@@ -72,6 +72,7 @@
self.fakePeripheral.openL2CAPChannelError = expectedError;
[self.l2capClient openL2CAPChannelWithPSM:psm
peripheral:self.fakePeripheral
completionHandler:^(GNCBLEL2CAPStream *stream, NSError *error) {
XCTAssertNotNil(error, @"Error should not be nil");
XCTAssertEqualObjects(error, expectedError);
@@ -84,6 +85,12 @@
- (void)testDisconnect {
self.requestDisconnectionHandlerExpectation =
[self expectationWithDescription:@"Request disconnection handler should be called"];
uint16_t psm = 123;
[self.l2capClient openL2CAPChannelWithPSM:psm
peripheral:self.fakePeripheral
completionHandler:^(GNCBLEL2CAPStream *stream, NSError *error){
}];
[self.l2capClient disconnect];
@@ -313,10 +313,9 @@ static NSString *const kServiceUUID = @"0000FEF3-0000-1000-8000-00805F9B34FB";
GNCFakePeripheral *fakePeripheral = [[GNCFakePeripheral alloc] init];
GNCBLEL2CAPClient *l2capClient =
[[GNCBLEL2CAPClient alloc] initWithPeripheral:fakePeripheral
queue:nil
requestDisconnectionHandler:^(id<GNCPeripheral> _Nonnull peripheral) {
}];
[[GNCBLEL2CAPClient alloc] initWithQueue:nil
requestDisconnectionHandler:^(id<GNCPeripheral> _Nonnull peripheral){
}];
[medium setL2CAPClient:l2capClient];
[medium openL2CAPChannelWithPSM:123
peripheral:fakePeripheral