diff --git a/ShhShell.xcodeproj/project.pbxproj b/ShhShell.xcodeproj/project.pbxproj index 2d6a7cb..3646498 100644 --- a/ShhShell.xcodeproj/project.pbxproj +++ b/ShhShell.xcodeproj/project.pbxproj @@ -10,7 +10,7 @@ A9083E402DF2226F0042906E /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = A9083E3F2DF2225A0042906E /* libz.tbd */; }; A92317282E07111E00ECE1E6 /* SwiftTerm in Frameworks */ = {isa = PBXBuildFile; productRef = A92317272E07111E00ECE1E6 /* SwiftTerm */; }; A923172A2E07113100ECE1E6 /* TerminalController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A92317292E07113100ECE1E6 /* TerminalController.swift */; }; - A923172D2E07138000ECE1E6 /* TerminalDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A923172C2E07138000ECE1E6 /* TerminalDelegate.swift */; }; + A923172D2E07138000ECE1E6 /* SSHTerminalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A923172C2E07138000ECE1E6 /* SSHTerminalView.swift */; }; A92538C82DEE0742007E0A18 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A92538C52DEE0742007E0A18 /* ContentView.swift */; }; A92538C92DEE0742007E0A18 /* ShhShellApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A92538C62DEE0742007E0A18 /* ShhShellApp.swift */; }; A92538CA2DEE0742007E0A18 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A92538C42DEE0742007E0A18 /* Assets.xcassets */; }; @@ -69,7 +69,7 @@ /* Begin PBXFileReference section */ A9083E3F2DF2225A0042906E /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; A92317292E07113100ECE1E6 /* TerminalController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalController.swift; sourceTree = ""; }; - A923172C2E07138000ECE1E6 /* TerminalDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalDelegate.swift; sourceTree = ""; }; + A923172C2E07138000ECE1E6 /* SSHTerminalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSHTerminalView.swift; sourceTree = ""; }; A925389A2DEE06DC007E0A18 /* ShhShell.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ShhShell.app; sourceTree = BUILT_PRODUCTS_DIR; }; A92538A72DEE06DE007E0A18 /* ShhShellTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ShhShellTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; A92538B12DEE06DE007E0A18 /* ShhShellUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ShhShellUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -132,7 +132,7 @@ isa = PBXGroup; children = ( A92317292E07113100ECE1E6 /* TerminalController.swift */, - A923172C2E07138000ECE1E6 /* TerminalDelegate.swift */, + A923172C2E07138000ECE1E6 /* SSHTerminalView.swift */, ); path = Terminal; sourceTree = ""; @@ -420,7 +420,7 @@ A98554592E0553AA009051BD /* KeyManager.swift in Sources */, A9C897EF2DF1A9A400EF9A5F /* SSHHandler.swift in Sources */, A98554552E05535F009051BD /* KeyManagerView.swift in Sources */, - A923172D2E07138000ECE1E6 /* TerminalDelegate.swift in Sources */, + A923172D2E07138000ECE1E6 /* SSHTerminalView.swift in Sources */, A923172A2E07113100ECE1E6 /* TerminalController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/ShhShell/SSH/SSHHandler.swift b/ShhShell/SSH/SSHHandler.swift index 6d31e6c..7652439 100644 --- a/ShhShell/SSH/SSHHandler.swift +++ b/ShhShell/SSH/SSHHandler.swift @@ -332,7 +332,8 @@ class SSHHandler: ObservableObject { logger.critical("\(String(cString: ssh_get_error(&self.session)))") } - func writeToChannel(_ string: String) { + func writeToChannel(_ string: String?) { + guard let string = string else { return } guard ssh_channel_is_open(channel) != 0 else { return } guard ssh_channel_is_eof(channel) == 0 else { return } @@ -343,4 +344,12 @@ class SSHHandler: ObservableObject { print("partial write!!") } } + + func resizeTTY(toRows: Int, toCols: Int) { + guard ssh_channel_is_open(channel) != 0 else { return } + guard ssh_channel_is_eof(channel) == 0 else { return } + + ssh_channel_change_pty_size(channel, Int32(toCols), Int32(toRows)) + print("resized tty to \(toRows)rows and \(toCols)cols") + } } diff --git a/ShhShell/Views/ConnectionView.swift b/ShhShell/Views/ConnectionView.swift index 74964a5..56d5752 100644 --- a/ShhShell/Views/ConnectionView.swift +++ b/ShhShell/Views/ConnectionView.swift @@ -132,8 +132,8 @@ struct ConnectionView: View { } NavigationLink() { - Button("Reload") { - handler.readFromChannel() + Button("send Ax256") { + handler.writeToChannel(Array(repeating: "A", count: 256).joined()) } TerminalController(handler: handler) } label: { diff --git a/ShhShell/Views/Terminal/SSHTerminalView.swift b/ShhShell/Views/Terminal/SSHTerminalView.swift new file mode 100644 index 0000000..3060b8e --- /dev/null +++ b/ShhShell/Views/Terminal/SSHTerminalView.swift @@ -0,0 +1,63 @@ +// +// SSHTerminalView.swift +// ShhShell +// +// Created by neon443 on 21/06/2025. +// + +import Foundation +import SwiftTerm + +class SSHTerminalView: TerminalView, TerminalViewDelegate { + var handler: SSHHandler? + var sshQueue: DispatchQueue + + public convenience init(frame: CGRect, handler: SSHHandler) { + self.init(frame: frame) + self.handler = handler + } + + public override init(frame: CGRect) { + sshQueue = DispatchQueue(label: "sshQueue") + + super.init(frame: frame) + terminalDelegate = self + } + + required init?(coder: NSCoder) { + fatalError("unimplemented") + } + + public func scrolled(source: TerminalView, position: Double) { + print("scrolled to \(position)") + } + + public func setTerminalTitle(source: TerminalView, title: String) { + print("set title to \(title)") + } + + public func sizeChanged(source: TerminalView, newCols: Int, newRows: Int) { + handler?.resizeTTY(toRows: newRows, toCols: newCols) + } + + public func send(source: TerminalView, data: ArraySlice) { + let dataSlice = Data(bytes: [data.first], count: data.count) + handler?.writeToChannel(String(data: dataSlice, encoding: .utf8)) + } + + public func clipboardCopy(source: TerminalView, content: Data) { + print(content) + } + + public func hostCurrentDirectoryUpdate(source: TerminalView, directory: String?) { + print("new dir: \(directory ?? "")") + } + + public func requestOpenLink(source: TerminalView, link: String, params: [String : String]) { + print("open link \(link) \(params)") + } + + public func rangeChanged(source: TerminalView, startY: Int, endY: Int) { + print(startY, endY) + } +} diff --git a/ShhShell/Views/Terminal/TerminalController.swift b/ShhShell/Views/Terminal/TerminalController.swift index 42631a7..d5f5e30 100644 --- a/ShhShell/Views/Terminal/TerminalController.swift +++ b/ShhShell/Views/Terminal/TerminalController.swift @@ -14,9 +14,14 @@ struct TerminalController: UIViewRepresentable { @ObservedObject var handler: SSHHandler func makeUIView(context: Context) -> TerminalView { - let tv = TerminalView() - let terminalDelegate = ShhTerminalViewDelegate() - tv.terminalDelegate = terminalDelegate + let tv = SSHTerminalView( + frame: CGRect( + origin: CGPoint(x: 0, y: 0), + size: CGSize(width: 100, height: 100) + ), + handler: handler + ) +// tv.terminalDelegate = terminalDelegate tv.getTerminal().feed(text: handler.readFromChannel()) return tv diff --git a/ShhShell/Views/Terminal/TerminalDelegate.swift b/ShhShell/Views/Terminal/TerminalDelegate.swift deleted file mode 100644 index d501481..0000000 --- a/ShhShell/Views/Terminal/TerminalDelegate.swift +++ /dev/null @@ -1,53 +0,0 @@ -// -// TerminalDelegate.swift -// ShhShell -// -// Created by neon443 on 21/06/2025. -// - -import Foundation -import SwiftTerm - -class ShhTerminalViewDelegate: TerminalViewDelegate { - func sizeChanged(source: TerminalView, newCols: Int, newRows: Int) { - print(newRows, newCols) - } - - func setTerminalTitle(source: TerminalView, title: String) { - print(title) - } - - func hostCurrentDirectoryUpdate(source: TerminalView, directory: String?) { - print(directory) - } - - func send(source: TerminalView, data: ArraySlice) { - print(data) - print("send") - } - - func scrolled(source: TerminalView, position: Double) { - print(position) - } - - func requestOpenLink(source: TerminalView, link: String, params: [String : String]) { - print(link) - print(params) - } - - func bell(source: TerminalView) { - print("ding") - } - - func clipboardCopy(source: TerminalView, content: Data) { - print(content) - } - - func iTermContent(source: TerminalView, content: ArraySlice) { - print("idk what this does") - } - - func rangeChanged(source: TerminalView, startY: Int, endY: Int) { - print(startY, endY) - } -}