-
-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add window change requests to server shell, and add a shell based on …
…SwiftTUI
- Loading branch information
Showing
5 changed files
with
150 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
.DS_Store | ||
/.build | ||
/Packages | ||
xcuserdata/ | ||
DerivedData/ | ||
.swiftpm/configuration/registries.json | ||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata | ||
.netrc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// swift-tools-version: 5.10 | ||
// The swift-tools-version declares the minimum version of Swift required to build this package. | ||
|
||
import PackageDescription | ||
|
||
let package = Package( | ||
name: "TerminalAppServer", | ||
platforms: [ | ||
.macOS(.v12), | ||
], | ||
dependencies: [ | ||
.package(url: "https://github.com/joannis/SwiftTUI.git", branch: "jo/allow-use-with-concurrency"), | ||
.package(path: "/Users/joannisorlandos/git/joannis/SwiftTUI"), | ||
], | ||
targets: [ | ||
// Targets are the basic building blocks of a package, defining a module or a test suite. | ||
// Targets can depend on other targets in this package and products from dependencies. | ||
.executableTarget( | ||
name: "TerminalAppServer", | ||
dependencies: [ | ||
.product(name: "Citadel", package: "Citadel"), | ||
.product(name: "SwiftTUI", package: "SwiftTUI"), | ||
] | ||
), | ||
] | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import Citadel | ||
import Crypto | ||
import Foundation | ||
import NIO | ||
import NIOFoundationCompat | ||
import NIOSSH | ||
import SwiftTUI | ||
|
||
@main struct ExampleSSHServer { | ||
static func main() async throws { | ||
let privateKey: Curve25519.Signing.PrivateKey | ||
let privateKeyURL = URL(fileURLWithPath: "./citadel_host_key_ed25519") | ||
|
||
// Read or create a private key | ||
if let file = try? Data(contentsOf: privateKeyURL) { | ||
// File exists, read it into a Curve25519 private key | ||
privateKey = try Curve25519.Signing.PrivateKey(sshEd25519: file) | ||
} else { | ||
// File does not exist, create a new Curve25519 private | ||
privateKey = Curve25519.Signing.PrivateKey() | ||
|
||
// Write the private key to a file | ||
try privateKey.makeSSHRepresentation().write(to: privateKeyURL, atomically: true, encoding: .utf8) | ||
} | ||
|
||
let server = try await SSHServer.host( | ||
host: "localhost", | ||
port: 2323, | ||
hostKeys: [ | ||
NIOSSHPrivateKey(ed25519Key: privateKey) | ||
], | ||
authenticationDelegate: LoginHandler(username: "joannis", password: "test") | ||
) | ||
|
||
server.enableShell(withDelegate: CustomAppShell()) | ||
|
||
try await server.closeFuture.get() | ||
} | ||
} | ||
|
||
final class CustomAppShell: ShellDelegate { | ||
@MainActor public func startShell( | ||
inbound: AsyncStream<ShellClientEvent>, | ||
outbound: ShellOutboundWriter, | ||
context: SSHShellContext | ||
) async throws { | ||
struct MyTerminalView: View { | ||
var body: some View { | ||
VStack { | ||
Text("Hello, world!") | ||
Button("Click me") { | ||
print("clicked") | ||
} | ||
Button("Don't click") { | ||
print("Clicked anyways") | ||
} | ||
} | ||
} | ||
} | ||
|
||
let app = Application(rootView: MyTerminalView()) { string in | ||
outbound.write(ByteBuffer(string: string)) | ||
} | ||
|
||
await withTaskGroup(of: Void.self) { group in | ||
group.addTask { @MainActor in | ||
for await message in inbound { | ||
if case .stdin(let input) = message { | ||
app.handleInput(Data(buffer: input)) | ||
} | ||
} | ||
} | ||
group.addTask { @MainActor in | ||
for await windowSize in context.windowSize { | ||
app.changeWindosSize(to: Size( | ||
width: Extended(windowSize.columns), | ||
height: Extended(windowSize.rows) | ||
)) | ||
} | ||
} | ||
|
||
app.draw() | ||
} | ||
} | ||
} | ||
|
||
struct LoginHandler: NIOSSHServerUserAuthenticationDelegate { | ||
let username: String | ||
let password: String | ||
|
||
var supportedAuthenticationMethods: NIOSSHAvailableUserAuthenticationMethods { | ||
.password | ||
} | ||
|
||
func requestReceived( | ||
request: NIOSSHUserAuthenticationRequest, | ||
responsePromise: EventLoopPromise<NIOSSHUserAuthenticationOutcome> | ||
) { | ||
if case .password(.init(password: password)) = request.request, request.username == username { | ||
return responsePromise.succeed(.success) | ||
} | ||
|
||
return responsePromise.succeed(.failure) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters