moved lots of logic into sshHandler

increased deployment target bc i cba rn
This commit is contained in:
neon443
2025-06-16 13:50:13 +01:00
parent 62eedee835
commit a9eeb55cf6
4 changed files with 107 additions and 81 deletions

View File

@@ -555,7 +555,7 @@
INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 14; IPHONEOS_DEPLOYMENT_TARGET = 16;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
@@ -586,7 +586,7 @@
INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 14; IPHONEOS_DEPLOYMENT_TARGET = 16;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",

View File

@@ -14,6 +14,8 @@ class SSHHandler: ObservableObject {
private var channel: ssh_channel? private var channel: ssh_channel?
@Published var authorized: Bool = false @Published var authorized: Bool = false
@Published var connected: Bool = false
@Published var testSuceeded: Bool = false
@Published var host: HostPr @Published var host: HostPr
@Published var terminal: String = "" @Published var terminal: String = ""
@@ -43,7 +45,7 @@ class SSHHandler: ObservableObject {
return Data(base64Encoded: String(cString: data)) return Data(base64Encoded: String(cString: data))
} }
func connect() -> Bool { func connect() {
defer { defer {
getAuthMethods() getAuthMethods()
self.host.key = getHostkey() self.host.key = getHostkey()
@@ -53,7 +55,8 @@ class SSHHandler: ObservableObject {
session = ssh_new() session = ssh_new()
guard session != nil else { guard session != nil else {
return false connected = false
return
} }
ssh_options_set(session, SSH_OPTIONS_HOST, host.address) ssh_options_set(session, SSH_OPTIONS_HOST, host.address)
@@ -64,9 +67,11 @@ class SSHHandler: ObservableObject {
if status != SSH_OK { if status != SSH_OK {
logger.critical("connection not ok: \(status)") logger.critical("connection not ok: \(status)")
logSshGetError() logSshGetError()
return false connected = false
return
} }
return true connected = true
return
} }
func disconnect() { func disconnect() {
@@ -81,26 +86,34 @@ class SSHHandler: ObservableObject {
host.key = nil host.key = nil
} }
func testExec() -> Bool { func testExec() {
if ssh_is_connected(session) == 0 { if ssh_is_connected(session) == 0 {
return false testSuceeded = false
return
} }
guard authorized else { return false } guard authorized else {
testSuceeded = false
return
}
var status: CInt var status: CInt
var buffer: [Int] = Array(repeating: 0, count: 256) var buffer: [Int] = Array(repeating: 0, count: 256)
var nbytes: CInt var nbytes: CInt
let channel = ssh_channel_new(session) let channel = ssh_channel_new(session)
guard channel != nil else { return false } guard channel != nil else {
testSuceeded = false
return
}
status = ssh_channel_open_session(channel) status = ssh_channel_open_session(channel)
guard status == SSH_OK else { guard status == SSH_OK else {
ssh_channel_free(channel) ssh_channel_free(channel)
logger.critical("session opening error") logger.critical("session opening error")
logSshGetError() logSshGetError()
return false testSuceeded = false
return
} }
status = ssh_channel_request_exec(channel, "uptime") status = ssh_channel_request_exec(channel, "uptime")
@@ -109,7 +122,8 @@ class SSHHandler: ObservableObject {
ssh_channel_free(channel) ssh_channel_free(channel)
logger.critical("session opening error") logger.critical("session opening error")
logSshGetError() logSshGetError()
return false testSuceeded = false
return
} }
nbytes = ssh_channel_read( nbytes = ssh_channel_read(
@@ -125,7 +139,8 @@ class SSHHandler: ObservableObject {
ssh_channel_free(channel) ssh_channel_free(channel)
logger.critical("write error") logger.critical("write error")
logSshGetError() logSshGetError()
return false testSuceeded = false
return
} }
nbytes = ssh_channel_read(channel, &buffer, UInt32(MemoryLayout.size(ofValue: Character.self)), 0) nbytes = ssh_channel_read(channel, &buffer, UInt32(MemoryLayout.size(ofValue: Character.self)), 0)
} }
@@ -135,14 +150,16 @@ class SSHHandler: ObservableObject {
ssh_channel_free(channel) ssh_channel_free(channel)
logger.critical("didnt read?") logger.critical("didnt read?")
logSshGetError() logSshGetError()
return false testSuceeded = false
return
} }
ssh_channel_send_eof(channel) ssh_channel_send_eof(channel)
ssh_channel_close(channel) ssh_channel_close(channel)
ssh_channel_free(channel) ssh_channel_free(channel)
print("testExec succeeded") print("testExec succeeded")
return true testSuceeded = true
return
} }
func authWithPubkey() -> Bool { func authWithPubkey() -> Bool {

View File

@@ -9,22 +9,24 @@ import SwiftUI
struct ContentView: View { struct ContentView: View {
@ObservedObject var handler: SSHHandler @ObservedObject var handler: SSHHandler
@State var connected: Bool = false // @State var connected: Bool = false
@State var testSucceded: Bool?
var body: some View { var body: some View {
VStack { NavigationStack {
Text(connected ? "connected" : "not connected") List {
.modifier(foregroundColorStyle(connected ? .green : .red)) HStack {
Text(handler.connected ? "connected" : "not connected")
.modifier(foregroundColorStyle(handler.connected ? .green : .red))
Text(handler.authorized ? "authorized" : "unauthorized") Text(handler.authorized ? "authorized" : "unauthorized")
.modifier(foregroundColorStyle(handler.authorized ? .green : .red)) .modifier(foregroundColorStyle(handler.authorized ? .green : .red))
if let testSucceded = testSucceded {
Image(systemName: testSucceded ? "checkmark.circle" : "xmark.circle")
.modifier(foregroundColorStyle(testSucceded ? .green : .red))
} }
// if let testSucceded = testSucceded {
// Image(systemName: testSucceded ? "checkmark.circle" : "xmark.circle")
// .modifier(foregroundColorStyle(testSucceded ? .green : .red))
// }
if handler.host.key != nil { if handler.host.key != nil {
Text("Hostkey: \(handler.host.key!.base64EncodedString())") Text("Hostkey: \(handler.host.key!.base64EncodedString())")
} }
@@ -47,40 +49,34 @@ struct ContentView: View {
TextField("password", text: $handler.host.password) TextField("password", text: $handler.host.password)
.textFieldStyle(.roundedBorder) .textFieldStyle(.roundedBorder)
Button("connect") { Button() {
if handler.connect() { handler.connect()
withAnimation { connected = true } let _ = handler.authWithPw()
}
handler.authWithPw()
}
.disabled(connected)
Button("disconnect") {
handler.disconnect()
withAnimation { testSucceded = false }
withAnimation { connected = false }
withAnimation { testSucceded = nil }
}
.disabled(!connected)
Button("run a test command") {
if handler.testExec() {
withAnimation { testSucceded = true }
} else {
withAnimation { testSucceded = false }
}
}
.disabled(!(connected && handler.authorized))
Button("request a shell") {
handler.openShell() handler.openShell()
} label: {
Label("Connect", systemImage: "powerplug.portrait")
} }
.disabled(handler.connected)
Button("read from server") { NavigationLink() {
handler.readFromChannel()
}
TerminalView(handler: handler) TerminalView(handler: handler)
} label: {
Label("Open Terminal", systemImage: "apple.terminal")
}
.disabled(!(handler.connected && handler.authorized))
Button() {
withAnimation { handler.testExec() }
} label: {
if handler.testSuceeded {
Image(systemName: handler.testSuceeded ? "checkmark.circle" : "xmark.circle")
.modifier(foregroundColorStyle(handler.testSuceeded ? .green : .red))
} else {
Label("Test Connection", systemImage: "checkmark")
}
}
.disabled(!(handler.connected && handler.authorized))
}
} }
} }
} }

View File

@@ -12,6 +12,19 @@ struct TerminalView: View {
@ObservedObject var handler: SSHHandler @ObservedObject var handler: SSHHandler
var body: some View { var body: some View {
HStack {
Button("read from server") {
handler.readFromChannel()
}
.fixedSize()
Spacer()
Button("disconnect") {
handler.disconnect()
withAnimation { handler.testSuceeded = false }
withAnimation { handler.connected = false }
}
.disabled(!handler.connected)
}
TextViewController(text: $handler.terminal) TextViewController(text: $handler.terminal)
} }
} }