Wrapper for NIOSSHClient (swift nio ssh client example)

Hi all. I'm trying to create a wrapper for the NIOSSHClient example that can be found in the apple/swift-nio-ssh repo. I want to use the ssh library to run commands on an ssh server from iOS in the following way:

let ssh = SwiftNioSshWrapper(host: "...", port: 22, user: "...", password: "...")
do {
    try ssh.run(command: "./script.sh")
} catch {
    print(error)
}

I was able to create that wrapper. But I can only use this once. If I try to create an instance for a second time, an exception is thrown (and the app crashes). For some reason closing the connection doesn't work as expected. I have uploaded my current wrapper to the following gist (adding it here would be too much of code). The wrapper is based on the main.swift file from the NIOSSHClient example. I have only removed the listener parts (and added some prints).

When I create an instance of SwiftNioSshWrapper and do run ssh.run(command:), then the command is actually executed on the connected ssh server. But then, the channel is not closed. closing is printed to the command line. child channel closed is not printed anymore.

Then line try! childChannel.closeFuture.wait() is blocking endlessly. Debugging the code, I was able to find the actual line that blocks in the NIOSSH library:

private func partnerWriteEOF() {
    print("func partnerWriteEOF")
    self.context?.close(mode: .output, promise: nil)
    print("func partnerWriteEOF closed")
}

The method partnerWriteEOF() never returns. I'm stuck here due to limited knowledge in Swift and SSH.

Can someone here help me to analyze the issue further? Or is there any idea on how to fix this properly?

2 Likes

Hi. Did you ever get this to work, @sarensw?

Not yet @sveinhal . The problem is still there. Starting mid of September I will be in touch with a couple of professional Swift developers who are supposed to fix this issue. Either in my code, or in the ssh lib. Fingers crossed :smile:

1 Like

Thanks for the update. If you ever find fixes, og makes improvements to some sort of high-level wrapper around swift-nio-ssh, feel free to update this thread, or keep me in the loop. I'm currently using NMSSH for an app I'm working on, and while it works, it hasn't been updated for 5+ years, and doesn't compile for the simulator. I'd love to be able to rip that code out of the app, and replace it with something newer.

1 Like

@sveinhal you could look into Citadel for your use cases. This code is based on NIOSSH, although I currently base it on a fork of NIOSSH until Custom Transport Algorithms are supported