mirror of
https://github.com/jeremysrand/ListenerApp.git
synced 2024-11-28 15:49:58 +00:00
Make sure nothing other than the UI holds a reference to the connection. This way, the connection should drop when the user switches to another destination. However, I am seeing a crash if the user switches to another destination while connected and listening.
This commit is contained in:
parent
b732007d68
commit
109213a577
@ -17,6 +17,21 @@
|
||||
</dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
<dict>
|
||||
<key>9D5155EE26A1EF7B0075EBC7</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>9D5155FF26A1EF7C0075EBC7</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>9D51560A26A1EF7C0075EBC7</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>9D62FC5F27C494D700AEE01F</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
|
@ -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("<h", data)
|
||||
if (unpacked[0] as? Int == GSConnection.LISTEN_SEND_MORE) {
|
||||
mainQueue.addOperation {
|
||||
self.canSend = true
|
||||
self.trySend()
|
||||
}
|
||||
} else {
|
||||
logger.error("Unexpected message on socket from \(self.destination)")
|
||||
errorOccurred(title: "Protocol Error", message: "Unexpected message from the GS")
|
||||
break
|
||||
}
|
||||
}
|
||||
catch {
|
||||
logger.error("Unable to unpack message on socket from \(self.destination)")
|
||||
errorOccurred(title: "Protocol Error", message: "Unexpected message from the GS")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
client.close()
|
||||
self.client = nil
|
||||
mainQueue.addOperation { self.disconnect() }
|
||||
}
|
||||
|
||||
func connect(destination : String) {
|
||||
self.destination = destination
|
||||
changeState(newState: .connecting)
|
||||
readQueue.addOperation {
|
||||
self.doConnect()
|
||||
readQueue.addOperation { [weak self, destination] in
|
||||
self?.logger.debug("Attempting to connect to \(destination)")
|
||||
let client = TCPClient(address: destination, port: Int32(GSConnection.port))
|
||||
switch client.connect(timeout: 10) {
|
||||
case .success:
|
||||
self?.mainQueue.addOperation {
|
||||
self?.client = client
|
||||
self?.connectionSuccessful()
|
||||
}
|
||||
case .failure(let error):
|
||||
client.close()
|
||||
self?.logger.error("Failed to connect to \(destination): \(String(describing: error))")
|
||||
self?.mainQueue.addOperation {
|
||||
self?.connectionFailed()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
while (true) {
|
||||
guard let byteArray = client.read(2) else {
|
||||
break
|
||||
}
|
||||
|
||||
if (byteArray.count != 2) {
|
||||
break
|
||||
}
|
||||
|
||||
guard let self = self else {
|
||||
break
|
||||
}
|
||||
let data = Data(byteArray)
|
||||
do {
|
||||
let unpacked = try unpack("<h", data)
|
||||
if (unpacked[0] as? Int == GSConnection.LISTEN_SEND_MORE) {
|
||||
self.mainQueue.addOperation {
|
||||
self.canSend = true
|
||||
self.trySend()
|
||||
}
|
||||
} else {
|
||||
self.logger.error("Unexpected message on socket from \(destination)")
|
||||
self.errorOccurred(title: "Protocol Error", message: "Unexpected message from the GS")
|
||||
break
|
||||
}
|
||||
}
|
||||
catch {
|
||||
self.logger.error("Unable to unpack message on socket from \(destination)")
|
||||
self.errorOccurred(title: "Protocol Error", message: "Unexpected message from the GS")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
self?.mainQueue.addOperation { self?.disconnect() }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>619</string>
|
||||
<string>645</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.utilities</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user