diff --git a/ListenerGS.xcodeproj/xcuserdata/jrand.xcuserdatad/xcschemes/xcschememanagement.plist b/ListenerGS.xcodeproj/xcuserdata/jrand.xcuserdatad/xcschemes/xcschememanagement.plist index 1486bb7..a42e73a 100644 --- a/ListenerGS.xcodeproj/xcuserdata/jrand.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/ListenerGS.xcodeproj/xcuserdata/jrand.xcuserdatad/xcschemes/xcschememanagement.plist @@ -17,6 +17,21 @@ SuppressBuildableAutocreation + 9D5155EE26A1EF7B0075EBC7 + + primary + + + 9D5155FF26A1EF7C0075EBC7 + + primary + + + 9D51560A26A1EF7C0075EBC7 + + primary + + 9D62FC5F27C494D700AEE01F primary diff --git a/ListenerGS/GSConnection.swift b/ListenerGS/GSConnection.swift index 535571d..fec9795 100644 --- a/ListenerGS/GSConnection.swift +++ b/ListenerGS/GSConnection.swift @@ -123,64 +123,61 @@ class GSConnection : ObservableObject { logger.debug("Connected to \(self.destination)") } - private func doConnect() { - logger.debug("Attempting to connect to \(self.destination)") - client = TCPClient(address: destination, port: Int32(GSConnection.port)) - guard let client = client else { - mainQueue.addOperation { self.connectionFailed() } - return - } - switch client.connect(timeout: 10) { - case .success: - mainQueue.addOperation { self.connectionSuccessful() } - case .failure(let error): - client.close() - self.client = nil - logger.error("Failed to connect to \(self.destination): \(String(describing: error))") - mainQueue.addOperation { self.connectionFailed() } - return - } - - while (true) { - guard let byteArray = client.read(2) else { - break - } - - if (byteArray.count != 2) { - break - } - - let data = Data(byteArray) - do { - let unpacked = try unpack("CFBundleShortVersionString 1.0 CFBundleVersion - 619 + 645 LSApplicationCategoryType public.app-category.utilities LSRequiresIPhoneOS diff --git a/ListenerGS/SpeechForwarder.swift b/ListenerGS/SpeechForwarder.swift index 2abe2af..59b3035 100644 --- a/ListenerGS/SpeechForwarder.swift +++ b/ListenerGS/SpeechForwarder.swift @@ -53,6 +53,7 @@ class SpeechForwarder : SpeechForwarderProtocol { audioEngine.stop() audioEngine.inputNode.removeTap(onBus: 0) recognitionTask?.cancel() + recognitionTask?.finish() recognitionRequest = nil recognitionTask = nil @@ -84,12 +85,15 @@ class SpeechForwarder : SpeechForwarderProtocol { // Create a recognition task for the speech recognition session. // Keep a reference to the task so that it can be canceled. - recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { result, error in + recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { [weak connection] result, error in var isFinal = false if let result = result { // Update the text view with the results. - OperationQueue.main.addOperation { connection.set(text: result.bestTranscription.formattedString) } + OperationQueue.main.addOperation { + guard let connection = connection else { return } + connection.set(text: result.bestTranscription.formattedString) + } isFinal = result.isFinal } @@ -99,6 +103,7 @@ class SpeechForwarder : SpeechForwarderProtocol { if error != nil || isFinal { OperationQueue.main.addOperation { + guard let connection = connection else { return } connection.stopListening() } } diff --git a/ListenerGS/SwiftSocket/UDPClient.swift b/ListenerGS/SwiftSocket/UDPClient.swift index 305ffb0..a3c39f5 100644 --- a/ListenerGS/SwiftSocket/UDPClient.swift +++ b/ListenerGS/SwiftSocket/UDPClient.swift @@ -116,7 +116,7 @@ open class UDPClient: Socket { guard let fd = self.fd else { return (nil, "no ip", 0) } - var buff: [Byte] = [Byte](repeating: 0x0, count: expectlen) + let buff: [Byte] = [Byte](repeating: 0x0, count: expectlen) var remoteipbuff: [Int8] = [Int8](repeating: 0x0, count: 16) var remoteport: Int32 = 0 let readLen: Int32 = c_yudpsocket_recive(fd, buff: buff, len: Int32(expectlen), ip: &remoteipbuff, port: &remoteport) @@ -154,7 +154,7 @@ open class UDPServer: Socket { //TODO add multycast and boardcast open func recv(_ expectlen: Int) -> ([Byte]?, String, Int) { if let fd = self.fd { - var buff: [Byte] = [Byte](repeating: 0x0,count: expectlen) + let buff: [Byte] = [Byte](repeating: 0x0,count: expectlen) var remoteipbuff: [Int8] = [Int8](repeating: 0x0,count: 16) var remoteport: Int32 = 0 let readLen: Int32 = c_yudpsocket_recive(fd, buff: buff, len: Int32(expectlen), ip: &remoteipbuff, port: &remoteport) diff --git a/ListenerGS/SwiftSocket/yudpsocket.c b/ListenerGS/SwiftSocket/yudpsocket.c index e59a725..128d8de 100644 --- a/ListenerGS/SwiftSocket/yudpsocket.c +++ b/ListenerGS/SwiftSocket/yudpsocket.c @@ -90,7 +90,7 @@ int yudpsocket_close(int socket_fd) { } //return socket fd -int yudpsocket_client() { +int yudpsocket_client(void) { //create socket int socketfd = socket(AF_INET, SOCK_DGRAM, 0); int reuseon = 1; diff --git a/ListenerGSTests/ListenerGSTests.swift b/ListenerGSTests/ListenerGSTests.swift index 197bf71..e43354a 100644 --- a/ListenerGSTests/ListenerGSTests.swift +++ b/ListenerGSTests/ListenerGSTests.swift @@ -337,8 +337,73 @@ class ListenerGSTests: XCTestCase { XCTAssertEqual(connection.textHeard, "Hello, everyone!") } - // Other tests: - // - Connection deconstruction - When I remove the reference to the connection, it stays up. I think self has references because of closures that are still running in the queues. + func testDestructWhileConnected() throws { + let server = GSServerMock() + + if (true) { + let connection = GSConnection() + connection.setMainQueueForTest() + + XCTAssertEqual(connection.state, .disconnected) + XCTAssertNil(connection.errorMessage) + XCTAssertEqual(connection.textHeard, "") + + connection.connect(destination: "127.0.0.1") + XCTAssertEqual(connection.state, .connecting) + XCTAssert(server.accept()) + + XCTAssert(server.hasClient()) + connection.waitForMain() + waitForConnection(connection: connection) + + XCTAssertEqual(connection.state, .connected) + XCTAssertNil(connection.errorMessage) + XCTAssertEqual(connection.textHeard, "") + } + + XCTAssert(server.getDisconnect()) + } + + /* This test hangs at the getDisconnect() line at the end. Something is holding a connection reference. + func testDestructWhileListening() throws { + let server = GSServerMock() + + if (true) { + let connection = GSConnection() + connection.setMainQueueForTest() + + XCTAssertEqual(connection.state, .disconnected) + XCTAssertNil(connection.errorMessage) + XCTAssertEqual(connection.textHeard, "") + + connection.connect(destination: "127.0.0.1") + XCTAssertEqual(connection.state, .connecting) + XCTAssert(server.accept()) + + XCTAssert(server.hasClient()) + connection.waitForMain() + waitForConnection(connection: connection) + + XCTAssertEqual(connection.state, .connected) + XCTAssertNil(connection.errorMessage) + XCTAssertEqual(connection.textHeard, "") + + let speechForwarder = SpeechForwarderMock() + XCTAssert(!speechForwarder.isListening) + + connection.listen(speechForwarder: speechForwarder) + XCTAssert(server.getListenState(isListening: true)) + connection.waitForMain() + + XCTAssert(speechForwarder.isListening) + XCTAssertEqual(connection.state, .listening) + XCTAssertNil(connection.errorMessage) + XCTAssertEqual(connection.textHeard, "") + } + + XCTAssert(server.getDisconnect()) + } + */ /* func testPerformanceExample() throws {