From 33068b99a0175731e10059f6359d90538cc0a0dd Mon Sep 17 00:00:00 2001 From: maddiebaka Date: Tue, 27 Jun 2023 18:41:22 -0400 Subject: [PATCH] Socket logic force disconnect/reconnect when server doesn't properly close it Amended to fix build --- Soyuz/ViewModels/BonjourBrowser.swift | 83 ++++++++++++++++--- Soyuz/ViewModels/MoonrakerSocketManager.swift | 28 +++++-- Soyuz/Views/PrinterConfigView.swift | 8 +- Soyuz/Views/SoyuzMenuBarExtraView.swift | 7 -- 4 files changed, 101 insertions(+), 25 deletions(-) diff --git a/Soyuz/ViewModels/BonjourBrowser.swift b/Soyuz/ViewModels/BonjourBrowser.swift index 6227237..1d7be8b 100755 --- a/Soyuz/ViewModels/BonjourBrowser.swift +++ b/Soyuz/ViewModels/BonjourBrowser.swift @@ -35,23 +35,27 @@ extension NWBrowser: NetworkDiscoveryEngine { // MARK: BonjourBrowser class BonjourBrowser: ObservableObject { - @Published var NDEngineResults: [NWBrowser.Result] = [] + @Published var networkResults: [NWBrowser.Result] = [] - private let nwBrowser: NetworkDiscoveryEngine - var connection: NWConnection! + private var nwBrowser: NWBrowser! + private var connection: NWConnection! - // TEMPORARY -// var bonjourListener: NWListener? - - init(browser: NetworkDiscoveryEngine = NWBrowser(for: .bonjourWithTXTRecord(type: "_moonraker._tcp", domain: "local."), using: .tcp)) { - nwBrowser = browser + + init() { + if nwBrowser == nil { + setup() + } + } + + func setup() { + nwBrowser = NWBrowser(for: .bonjourWithTXTRecord(type: "_moonraker._tcp", domain: "local."), using: .tcp) // Bonjour browser results changed handler nwBrowser.setBrowseResultsChangedHandler({ (newResults, changes) in print("[update] Results changed.") - self.NDEngineResults.removeAll() + self.networkResults.removeAll() newResults.forEach { result in print(result) - self.NDEngineResults.append(result) + self.networkResults.append(result) } }) @@ -72,4 +76,63 @@ class BonjourBrowser: ObservableObject { nwBrowser.startScan(queue: DispatchQueue.main) } + func enableScan(_ queue: DispatchQueue) { + if(nwBrowser.state == .cancelled) { + self.setup() + } + nwBrowser.start(queue: queue) + } + + func disableScan() { + if(nwBrowser.state != .cancelled) { + nwBrowser.cancel() + } + } } + +//class BonjourBrowser: ObservableObject { +// @Published var NDEngineResults: [NWBrowser.Result] = [] +// +// private let nwBrowser: NetworkDiscoveryEngine +// var connection: NWConnection! +// +// // TEMPORARY +//// var bonjourListener: NWListener? +// +// init(browser: NetworkDiscoveryEngine = NWBrowser(for: .bonjourWithTXTRecord(type: "_moonraker._tcp", domain: "local."), using: .tcp)) { +// nwBrowser = browser +// // Bonjour browser results changed handler +// nwBrowser.setBrowseResultsChangedHandler({ (newResults, changes) in +// print("[update] Results changed.") +// self.NDEngineResults.removeAll() +// newResults.forEach { result in +// print(result) +// self.NDEngineResults.append(result) +// } +// }) +// +// // Bonjour browser state update handler +// nwBrowser.setStateUpdateHandler({ newState in +// switch newState { +// case .failed(let error): +// print("[error] nwbrowser: \(error)") +// case .ready: +// print("[ready] nwbrowser") +// case .setup: +// print("[setup] nwbrowser") +// default: +// break +// } +// }) +// +// nwBrowser.startScan(queue: DispatchQueue.main) +// } +// +// func startScanning(queue: DispatchQueue.main) { +// if(self.nwBrowser.state == NWBrowser.State.cancelled) { +// +// } +// self.nwBrowser.startScan(queue) +// } +// +//} diff --git a/Soyuz/ViewModels/MoonrakerSocketManager.swift b/Soyuz/ViewModels/MoonrakerSocketManager.swift index 5d77303..dc429a1 100755 --- a/Soyuz/ViewModels/MoonrakerSocketManager.swift +++ b/Soyuz/ViewModels/MoonrakerSocketManager.swift @@ -74,7 +74,7 @@ class MoonrakerSocketManager: ObservableObject, WebSocketDelegate { // socket?.disconnect() // } // - if connection == nil { + if connection == nil || connection?.state == .cancelled { connection = NWConnection(to: endpoint, using: .tcp) } @@ -112,25 +112,29 @@ class MoonrakerSocketManager: ObservableObject, WebSocketDelegate { func disconnect() { print("disconnect() called") - isConnected = false - //connection?.cancel() - connection = nil + self.isConnected = false socket?.disconnect() + socket = nil } // MARK: Private functions // Opens the websocket connection - private func openWebsocket() { + func openWebsocket() { // Exit function if there is no server to connect to if socketHost.isEmpty || socketPort.isEmpty { return } + if socket != nil { + socket!.connect() + return + } + lastPingDate = Date.now - var request = URLRequest(url: URL(string: "http://\(socketHost):\(socketPort)/websocket")!) + var request = URLRequest(url: URL(string: "ws://\(socketHost):\(socketPort)/websocket")!) request.timeoutInterval = 30 socket = WebSocket(request: request, engine: starscreamEngine) socket!.delegate = self @@ -154,7 +158,8 @@ class MoonrakerSocketManager: ObservableObject, WebSocketDelegate { switch(notification.name) { case NSWorkspace.screensDidSleepNotification: print("Screen slept. Disconnecting..") - socket?.disconnect() + self.disconnect() + //socket?.disconnect() case NSWorkspace.screensDidWakeNotification: print("Screen awoke. Opening websocket..") self.openWebsocket() @@ -216,6 +221,15 @@ class MoonrakerSocketManager: ObservableObject, WebSocketDelegate { case .error(let error): isConnected = false print("[error] Starscream: \(error.debugDescription)") + switch(error) { + case .some(HTTPUpgradeError.notAnUpgrade(200)): + print("[debug] Starscream: Forcing disconnect and reconnect..") + self.socket?.forceDisconnect() + self.socket = nil + self.openWebsocket() + default: + break + } } } diff --git a/Soyuz/Views/PrinterConfigView.swift b/Soyuz/Views/PrinterConfigView.swift index d3fdcc6..949499e 100755 --- a/Soyuz/Views/PrinterConfigView.swift +++ b/Soyuz/Views/PrinterConfigView.swift @@ -13,6 +13,8 @@ struct PrinterConfigView: View { @ObservedObject var printerManager: MoonrakerSocketManager @ObservedObject var bonjourBrowser = BonjourBrowser() + //@State var bonjourBrowser = NWBrowser(for: .bonjourWithTXTRecord(type: "_moonraker._tcp", domain: "local."), using: .tcp) + @Environment(\.openURL) private var openURL @@ -61,7 +63,7 @@ struct PrinterConfigView: View { }.buttonStyle(PlainButtonStyle()) } - ForEach(bonjourBrowser.NDEngineResults , id: \.hashValue) { result in + ForEach(bonjourBrowser.networkResults, id: \.hashValue) { result in HStack { Text(result.endpoint.toFriendlyString()) Button { @@ -79,6 +81,10 @@ struct PrinterConfigView: View { } .onAppear { NSApplication.shared.activate(ignoringOtherApps: true) + bonjourBrowser.enableScan(DispatchQueue.main) + } + .onDisappear { + bonjourBrowser.disableScan() } } } diff --git a/Soyuz/Views/SoyuzMenuBarExtraView.swift b/Soyuz/Views/SoyuzMenuBarExtraView.swift index 0793ab1..67916f1 100755 --- a/Soyuz/Views/SoyuzMenuBarExtraView.swift +++ b/Soyuz/Views/SoyuzMenuBarExtraView.swift @@ -86,13 +86,6 @@ struct SoyuzMenuBarExtraView: View { Text("Printers") .foregroundColor(Color("ButtonForegroundColor")) } - /* Debugging Stuff */ - Button { - notification.sendNotification(.printComplete) - } label: { - Text("Notify") - } - /* Debugging Stuff */ Spacer() if(printerManager.isConnected) { Image(systemName: "network")