From 251d6efe411be18eb592e16aba7ecc994b6d1e49 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Tue, 11 Sep 2018 19:44:01 -0500 Subject: [PATCH 1/2] Make L2CAPSocket non-blocking --- Sources/ATTConnection.swift | 19 +++++++++++-------- Sources/GATTClient.swift | 8 ++++---- Sources/GATTServer.swift | 4 ++-- Sources/L2CAPSocket.swift | 2 +- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/Sources/ATTConnection.swift b/Sources/ATTConnection.swift index 04ad32676..1eb3ac709 100755 --- a/Sources/ATTConnection.swift +++ b/Sources/ATTConnection.swift @@ -64,13 +64,14 @@ public final class ATTConnection { // MARK: - Methods /// Performs the actual IO for recieving data. - public func read() throws { + public func read() throws -> Bool { - log?("Attempt read") + //log?("Attempt read") - let recievedData = try socket.recieve(Int(maximumTransmissionUnit.rawValue)) + guard let recievedData = try socket.recieve(Int(maximumTransmissionUnit.rawValue)) + else { return false } // no data availible to read - log?("Recieved data (\(recievedData.count) bytes)") + //log?("Recieved data (\(recievedData.count) bytes)") // valid PDU data length guard recievedData.count >= ATT.minimumPDULength @@ -82,7 +83,7 @@ public final class ATTConnection { guard let opcode = ATT.Opcode(rawValue: opcodeByte) else { throw Error.garbageResponse(recievedData) } - log?("Recieved opcode \(opcode)") + //log?("Recieved opcode \(opcode)") // Act on the received PDU based on the opcode type switch opcode.type { @@ -106,25 +107,27 @@ public final class ATTConnection { // For all other opcodes notify the upper layer of the PDU and let them act on it. try handle(notify: recievedData, opcode: opcode) } + + return true } /// Performs the actual IO for sending data. public func write() throws -> Bool { - log?("Attempt write") + //log?("Attempt write") guard let sendOperation = pickNextSendOpcode() else { return false } assert(sendOperation.data.count <= Int(maximumTransmissionUnit.rawValue), "Trying to send \(sendOperation.data.count) bytes when MTU is \(maximumTransmissionUnit)") - log?("Sending data... (\(sendOperation.data.count) bytes)") + //log?("Sending data... (\(sendOperation.data.count) bytes)") try socket.send(sendOperation.data) let opcode = sendOperation.opcode - log?("Did write \(opcode)") + //log?("Did write \(opcode)") /* Based on the operation type, set either the pending request or the * pending indication. If it came from the write queue, then there is diff --git a/Sources/GATTClient.swift b/Sources/GATTClient.swift index 7c0edd488..d729d2b5e 100755 --- a/Sources/GATTClient.swift +++ b/Sources/GATTClient.swift @@ -70,9 +70,9 @@ public final class GATTClient { // MARK: - Methods /// Performs the actual IO for recieving data. - public func read() throws { + public func read() throws -> Bool { - try connection.read() + return try connection.read() } /// Performs the actual IO for sending data. @@ -346,8 +346,8 @@ public final class GATTClient { private func registerATTHandlers() { // value notifications / indications - connection.register(notification) - connection.register(indication) + connection.register { [weak self] in self?.notification($0) } + connection.register { [weak self] in self?.indication($0) } } @inline(__always) diff --git a/Sources/GATTServer.swift b/Sources/GATTServer.swift index 17abf4364..86dd9e230 100644 --- a/Sources/GATTServer.swift +++ b/Sources/GATTServer.swift @@ -68,9 +68,9 @@ public final class GATTServer { // MARK: - Methods /// Performs the actual IO for sending data. - public func read() throws { + public func read() throws -> Bool { - try connection.read() + return try connection.read() } /// Performs the actual IO for recieving data. diff --git a/Sources/L2CAPSocket.swift b/Sources/L2CAPSocket.swift index 226cc35b8..5f66089b0 100644 --- a/Sources/L2CAPSocket.swift +++ b/Sources/L2CAPSocket.swift @@ -21,7 +21,7 @@ public protocol L2CAPSocketProtocol { var channelIdentifier: UInt16 { get } /// Reads from the socket. - func recieve(_ bufferSize: Int) throws -> Data + func recieve(_ bufferSize: Int) throws -> Data? /// Write to the socket. func send(_ data: Data) throws From 464c0234a3ec5221a0f03068f67be67a0b525ed6 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Tue, 11 Sep 2018 22:13:39 -0500 Subject: [PATCH 2/2] Updated unit tests --- Tests/BluetoothTests/GATTTests.swift | 12 ++++++++---- Tests/BluetoothTests/L2CAPSocket.swift | 5 +++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Tests/BluetoothTests/GATTTests.swift b/Tests/BluetoothTests/GATTTests.swift index ad97327c9..15cbd84af 100644 --- a/Tests/BluetoothTests/GATTTests.swift +++ b/Tests/BluetoothTests/GATTTests.swift @@ -652,7 +652,8 @@ final class GATTTests: XCTestCase { server.writePending = { do { while try server.write() { - try client.read() + let didRead = try client.read() + XCTAssert(didRead) } } catch { XCTFail("Error: \(error)") } @@ -661,7 +662,8 @@ final class GATTTests: XCTestCase { client.writePending = { do { while try client.write() { - try server.read() + let didRead = try server.read() + XCTAssert(didRead) } } catch { XCTFail("Error: \(error)") } @@ -1022,7 +1024,8 @@ extension GATTTests { while server.socket.input.isEmpty == false { - try server.gatt.read() + let didRead = try server.gatt.read() + assert(didRead) } while try server.gatt.write() { @@ -1032,7 +1035,8 @@ extension GATTTests { while client.socket.input.isEmpty == false { - try client.gatt.read() + let didRead = try client.gatt.read() + assert(didRead) } } while didWrite diff --git a/Tests/BluetoothTests/L2CAPSocket.swift b/Tests/BluetoothTests/L2CAPSocket.swift index acff17720..255109431 100644 --- a/Tests/BluetoothTests/L2CAPSocket.swift +++ b/Tests/BluetoothTests/L2CAPSocket.swift @@ -68,10 +68,11 @@ internal final class TestL2CAPSocket: L2CAPSocketProtocol { } /// Reads from the socket. - func recieve(_ bufferSize: Int) throws -> Data { + @discardableResult + func recieve(_ bufferSize: Int) throws -> Data? { guard let sentData = self.input.popFirst() - else { throw POSIXError(code: .EBUSY) } + else { return nil } let readData = Data(sentData.prefix(bufferSize))