improved disconnection - will dismiss terminal on exit

-- before you had to type more to exit
improved connection logic with a try catch
improved disconnection doesnt crash
fix [int] to [cchar] reduced mem usage
code cleanup
try? -> catch print(error.localizedDesc)
guard let var = var  else ---> guard let var else
removed file importers as it didnt eork
compbined guards in writetochannel
This commit is contained in:
neon443
2025-06-25 11:40:25 +01:00
parent f71bd0ddf2
commit db36c56f29
3 changed files with 45 additions and 67 deletions

View File

@@ -58,13 +58,18 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
return
}
guard let _ = try? connect() else { return }
do {
try connect()
} catch {
print("error in connect \(error.localizedDescription)")
}
guard connected else { return }
if !host.password.isEmpty {
do { try authWithPw() } catch {
print("pw auth error")
print(error.localizedDescription)
}
} else {
do {
@@ -74,6 +79,7 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
}
} catch {
print("error with pubkey auth")
print(error.localizedDescription)
}
}
openShell()
@@ -121,7 +127,10 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
withAnimation { testSuceeded = nil }
}
ssh_channel_send_eof(self.channel)
//send eof if open
if ssh_channel_is_open(channel) == 1 {
ssh_channel_send_eof(channel)
}
ssh_channel_free(self.channel)
self.channel = nil
@@ -157,7 +166,7 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
}
var status: CInt
var buffer: [Int] = Array(repeating: 0, count: 256)
var buffer: [CChar] = Array(repeating: 0, count: 256)
var nbytes: CInt
let channel = ssh_channel_new(session)
@@ -236,8 +245,13 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
fileManager.createFile(atPath: tempPubkey.path(), contents: nil)
fileManager.createFile(atPath: tempKey.path(), contents: nil)
try? pubInp.write(to: tempPubkey, options: .completeFileProtection)
try? privInp.write(to: tempKey, options: .completeFileProtection)
do {
try pubInp.write(to: tempPubkey, options: .completeFileProtection)
try privInp.write(to: tempKey, options: .completeFileProtection)
} catch {
print("file writing error")
print(error.localizedDescription)
}
let attributes: [FileAttributeKey: Any] = [.posixPermissions: 0o600]
do {
@@ -271,8 +285,13 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
ssh_key_free(pubkey)
ssh_key_free(privkey)
try? FileManager.default.removeItem(at: tempPubkey)
try? FileManager.default.removeItem(at: tempKey)
do {
try FileManager.default.removeItem(at: tempPubkey)
try FileManager.default.removeItem(at: tempKey)
} catch {
print("error removing file")
print(error.localizedDescription)
}
return
}
@@ -328,7 +347,7 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
var status: CInt
channel = ssh_channel_new(session)
guard let channel = channel else { return }
guard let channel else { return }
status = ssh_channel_open_session(channel)
guard status == SSH_OK else {
@@ -356,7 +375,7 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
func readFromChannel() -> String? {
guard connected else { return nil }
guard ssh_channel_is_open(channel) != 0 || ssh_channel_is_eof(channel) == 0 else {
guard ssh_channel_is_open(channel) == 1 && ssh_channel_is_eof(channel) == 0 else {
Task { await disconnect() }
return nil
}
@@ -376,19 +395,12 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
return nil
}
private func logSshGetError() {
logger.critical("\(String(cString: ssh_get_error(&self.session)))")
}
private func logCritical(_ logMessage: String) {
logger.critical("\(logMessage)")
}
func writeToChannel(_ string: String?) {
guard let string = string else { return }
guard channel != nil else { return }
guard ssh_channel_is_open(channel) != 0 else { return }
guard ssh_channel_is_eof(channel) == 0 else { return }
guard let string else { return }
guard ssh_channel_is_open(channel) == 1 && ssh_channel_is_eof(channel) == 0 else {
Task { await disconnect() }
return
}
var buffer: [CChar] = []
for byte in string.utf8 {
@@ -408,4 +420,13 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
ssh_channel_change_pty_size(channel, Int32(toCols), Int32(toRows))
// print("resized tty to \(toRows)rows and \(toCols)cols")
}
private func logSshGetError() {
guard var session = self.session else { return }
logger.critical("\(String(cString: ssh_get_error(&session)))")
}
private func logCritical(_ logMessage: String) {
logger.critical("\(logMessage)")
}
}

View File

@@ -18,8 +18,6 @@ struct ConnectionView: View {
@State var privkeyStr: String = ""
@State var showTerminal: Bool = false
@State var privPickerPresented: Bool = false
@State var pubPickerPresented: Bool = false
@State var hostKeyChangedAlert: Bool = false
@@ -65,26 +63,6 @@ struct ConnectionView: View {
let newStr = pubkeyStr.replacingOccurrences(of: "\r\n", with: "")
handler.host.publicKey = Data(newStr.utf8)
}
Button() {
pubPickerPresented.toggle()
} label: {
Image(systemName: "folder")
}
.buttonStyle(.plain)
.fileImporter(isPresented: $pubPickerPresented, allowedContentTypes: [.item, .content, .data]) { (Result) in
do {
let fileURL = try Result.get()
guard fileURL.startAccessingSecurityScopedResource() else {
print("cant acces file")
return
}
defer { fileURL.stopAccessingSecurityScopedResource() }
handler.host.publicKey = try? Data(contentsOf: fileURL)
print(fileURL)
} catch {
print(error.localizedDescription)
}
}
}
HStack {
@@ -93,27 +71,6 @@ struct ConnectionView: View {
let newStr = privkeyStr.replacingOccurrences(of: "\r\n", with: "")
handler.host.privateKey = Data(newStr.utf8)
}
Button() {
privPickerPresented.toggle()
} label: {
Image(systemName: "folder")
}
.buttonStyle(.plain)
.fileImporter(isPresented: $privPickerPresented, allowedContentTypes: [.item, .content, .data]) { (Result) in
do {
let fileURL = try Result.get()
guard fileURL.startAccessingSecurityScopedResource() else {
print("cant access file")
return
}
defer { fileURL.stopAccessingSecurityScopedResource() }
handler.host.privateKey = try? Data(contentsOf: fileURL)
print(handler.host.privateKey ?? "")
print(fileURL)
} catch {
print(error.localizedDescription)
}
}
}
TextField("", text: $passphrase, prompt: Text("Passphrase (Optional)"))
}

View File

@@ -31,7 +31,7 @@ final class SSHTerminalView: TerminalView, Sendable, @preconcurrency TerminalVie
while handler.connected {
if let read = handler.readFromChannel() {
Task { [weak self] in
guard let self = self else { return }
guard let self else { return }
await self.feed(text: read)
}
} else {
@@ -50,7 +50,7 @@ final class SSHTerminalView: TerminalView, Sendable, @preconcurrency TerminalVie
while handler.connected {
if let read = handler.readFromChannel() {
Task { [weak self] in
guard let self = self else { return }
guard let self else { return }
await self.feed(text: read)
}
} else {