Implement openL2CAPServerWithCompletionHandler in GNCBLEMedium class.

PiperOrigin-RevId: 745877478
This commit is contained in:
Edwin Wu
2025-04-09 22:58:34 -07:00
committed by Copybara-Service
parent 675e4f738f
commit 7f488271f1
4 changed files with 77 additions and 0 deletions
@@ -18,7 +18,9 @@
@class GNCBLEGATTServer;
@class GNCBLEGATTClient;
@class GNCBLEGATTCharacteristic;
@class GNCBLEL2CAPServer;
@protocol GNCPeripheralManager;
@protocol GNCPeripheral;
NS_ASSUME_NONNULL_BEGIN
@@ -87,6 +89,15 @@ typedef void (^GNCGATTDisconnectionHandler)();
typedef void (^GNCGATTConnectionCompletionHandler)(GNCBLEGATTClient *_Nullable client,
NSError *_Nullable error);
/**
* A block to be invoked when a call to @c openL2CAPServerWithCompletionHandler: has completed.
*
* @param server The successfully started L2CAP server, or @c nil if an error occurred.
* @param error The cause of the failure, or @c nil if no error occurred.
*/
typedef void (^GNCOpenL2CAPServerCompletionHandler)(GNCBLEL2CAPServer *_Nullable server,
NSError *_Nullable error);
/**
* The main BLE medium used inside of Nearby. This serves as the entry point for all BLE and GATT
* related operations.
@@ -181,6 +192,16 @@ typedef void (^GNCGATTConnectionCompletionHandler)(GNCBLEGATTClient *_Nullable c
completionHandler:
(nullable GNCGATTConnectionCompletionHandler)completionHandler;
/**
* Opens a L2CAP server.
*
* @param completionHandler Called on a private queue with the L2CAP server if successfully started
* or an error if one has occured.
* @param peripheralManager The peripheral manager instance.
*/
- (void)openL2CAPServerWithCompletionHandler:(GNCOpenL2CAPServerCompletionHandler)completionHandler
peripheralManager:(nullable id<GNCPeripheralManager>)peripheralManager;
@end
NS_ASSUME_NONNULL_END
@@ -20,6 +20,7 @@
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEError.h"
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEGATTClient.h"
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEGATTServer.h"
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEL2CAPServer.h"
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCCentralManager.h"
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCPeripheral.h"
#import "internal/platform/implementation/apple/Mediums/BLEv2/NSData+GNCBase85.h"
@@ -33,6 +34,16 @@ static NSError *AlreadyScanningError() {
return [NSError errorWithDomain:GNCBLEErrorDomain code:GNCBLEErrorAlreadyScanning userInfo:nil];
}
static GNCBLEL2CAPServer *_Nonnull CreateL2CapServer(
id<GNCPeripheralManager> _Nullable peripheralManager) {
if (!peripheralManager) {
return [[GNCBLEL2CAPServer alloc] init];
} else {
return [[GNCBLEL2CAPServer alloc] initWithPeripheralManager:peripheralManager
queue:dispatch_get_main_queue()];
}
}
@interface GNCBLEMedium () <GNCCentralManagerDelegate, CBCentralManagerDelegate>
@end
@@ -42,6 +53,7 @@ static NSError *AlreadyScanningError() {
// The active GATT server, or @nil if one hasn't been started yet.
GNCBLEGATTServer *_server;
GNCBLEL2CAPServer *_l2capServer;
// The services that is being actively scanned for.
NSMutableArray<CBUUID *> *_scanningServiceUUIDs;
@@ -181,6 +193,26 @@ static NSError *AlreadyScanningError() {
});
}
- (void)openL2CAPServerWithCompletionHandler:(GNCOpenL2CAPServerCompletionHandler)completionHandler
peripheralManager:(nullable id<GNCPeripheralManager>)peripheralManager {
// Capture the completion handler.
GNCOpenL2CAPServerCompletionHandler localCompletionHandler = completionHandler;
dispatch_async(_queue, ^{
if (!_l2capServer) {
_l2capServer = CreateL2CapServer(peripheralManager);
}
__weak __typeof__(GNCBLEL2CAPServer *) weakL2capServer = _l2capServer;
[_l2capServer startListeningChannelWithCompletionHandler:^(NSError *error) {
__typeof__(GNCBLEL2CAPServer *) strongL2capServer = weakL2capServer;
if (error) {
localCompletionHandler(nil, error);
return;
}
localCompletionHandler(strongL2capServer, nil);
}];
});
}
#pragma mark - Internal
- (void)internalStartScanningIfPoweredOn {
@@ -17,6 +17,7 @@
#import <Foundation/Foundation.h>
@protocol GNCCentralManager;
@protocol GNCPeripheralManager;
NS_ASSUME_NONNULL_BEGIN
@@ -24,6 +24,7 @@
#import "internal/platform/implementation/apple/Tests/GNCBLEMedium+Testing.h"
#import "internal/platform/implementation/apple/Tests/GNCFakeCentralManager.h"
#import "internal/platform/implementation/apple/Tests/GNCFakePeripheral.h"
#import "internal/platform/implementation/apple/Tests/GNCFakePeripheralManager.h"
static NSString *const kServiceUUID = @"0000FEF3-0000-1000-8000-00805F9B34FB";
@@ -273,6 +274,28 @@ static NSString *const kServiceUUID = @"0000FEF3-0000-1000-8000-00805F9B34FB";
[self waitForExpectations:@[ expectation ] timeout:3];
}
#pragma mark - Open L2CAP Channel
- (void)testOpenL2CAPServerSocket {
GNCFakeCentralManager *fakeCentralManager = [[GNCFakeCentralManager alloc] init];
GNCFakePeripheralManager *fakePeripheralManager = [[GNCFakePeripheralManager alloc] init];
[fakePeripheralManager simulatePeripheralManagerDidUpdateState:CBManagerStatePoweredOn];
GNCBLEMedium *medium = [[GNCBLEMedium alloc] initWithCentralManager:fakeCentralManager queue:nil];
XCTestExpectation *expectation =
[[XCTestExpectation alloc] initWithDescription:@"Open L2CAP server."];
// Open L2CAP server is fully covered with @c GNCBLEL2CAPServer tests.
[medium
openL2CAPServerWithCompletionHandler:^(GNCBLEL2CAPServer *l2capServer, NSError *error) {
XCTAssertNotNil(l2capServer);
XCTAssertNil(error);
[expectation fulfill];
}
peripheralManager:fakePeripheralManager];
[self waitForExpectations:@[ expectation ] timeout:3];
}
#pragma mark - Connect
- (void)testSuccessfulConnect {