From 7fbfc9df903988dc2755ccd02e48f2c1754e7630 Mon Sep 17 00:00:00 2001 From: ShellWen Chen Date: Sat, 15 Jun 2024 16:41:17 +0800 Subject: [PATCH] fix: remove sshd instance when start second time due to sshd can't be start after stop --- .../Plugins/SftpPlugin/SftpPlugin.kt | 2 +- .../Plugins/SftpPlugin/SimpleSftpServer.kt | 39 ++++++++++++++++--- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/org/kde/kdeconnect/Plugins/SftpPlugin/SftpPlugin.kt b/src/org/kde/kdeconnect/Plugins/SftpPlugin/SftpPlugin.kt index ba230dfe..5bcb5ce3 100644 --- a/src/org/kde/kdeconnect/Plugins/SftpPlugin/SftpPlugin.kt +++ b/src/org/kde/kdeconnect/Plugins/SftpPlugin/SftpPlugin.kt @@ -79,7 +79,7 @@ class SftpPlugin : Plugin(), OnSharedPreferenceChangeListener { override fun onPacketReceived(np: NetworkPacket): Boolean { if (!np.getBoolean("startBrowsing")) return false - if (!server.isInitialized) { + if (!server.isInitialized || server.isClosed) { try { server.initialize(context, device) } catch (e: GeneralSecurityException) { diff --git a/src/org/kde/kdeconnect/Plugins/SftpPlugin/SimpleSftpServer.kt b/src/org/kde/kdeconnect/Plugins/SftpPlugin/SimpleSftpServer.kt index 0a19acc4..9077be5d 100644 --- a/src/org/kde/kdeconnect/Plugins/SftpPlugin/SimpleSftpServer.kt +++ b/src/org/kde/kdeconnect/Plugins/SftpPlugin/SimpleSftpServer.kt @@ -24,15 +24,22 @@ import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator import org.apache.sshd.server.kex.DHGServer import org.apache.sshd.server.session.ServerSession import org.apache.sshd.server.subsystem.SubsystemFactory +import org.apache.sshd.sftp.server.FileHandle +import org.apache.sshd.sftp.server.SftpFileSystemAccessor import org.apache.sshd.sftp.server.SftpSubsystemFactory +import org.apache.sshd.sftp.server.SftpSubsystemProxy import org.kde.kdeconnect.Device import org.kde.kdeconnect.Helpers.RandomHelper import org.kde.kdeconnect.Helpers.SecurityHelpers.RsaHelper import org.kde.kdeconnect.Helpers.SecurityHelpers.constantTimeCompare import org.kde.kdeconnect.Plugins.SftpPlugin.saf.SafFileSystemFactory +import org.kde.kdeconnect.Plugins.SftpPlugin.saf.SafPath import java.io.IOException +import java.nio.channels.SeekableByteChannel import java.nio.charset.StandardCharsets +import java.nio.file.OpenOption import java.nio.file.Path +import java.nio.file.attribute.FileAttribute import java.security.GeneralSecurityException import java.security.KeyPair import java.security.MessageDigest @@ -50,7 +57,9 @@ internal class SimpleSftpServer { var isInitialized: Boolean = false - private lateinit var sshd: SshServer + private var sshd: SshServer? = null + val isClosed: Boolean + get() = sshd!!.isClosed private var safFileSystemFactory: SafFileSystemFactory? = null @@ -60,7 +69,7 @@ internal class SimpleSftpServer { @Throws(GeneralSecurityException::class) fun initialize(context: Context?, device: Device) { - sshd = ServerBuilder.builder().apply { + val sshd = ServerBuilder.builder().apply { signatureFactories( listOf( BuiltinSignatures.nistp256, @@ -102,7 +111,23 @@ internal class SimpleSftpServer { sshd.commandFactory = ScpCommandFactory() sshd.subsystemFactories = - listOf(SftpSubsystemFactory()) + listOf(SftpSubsystemFactory.Builder().apply { + withFileSystemAccessor(object: SftpFileSystemAccessor { + override fun openFile( + subsystem: SftpSubsystemProxy?, + fileHandle: FileHandle?, + file: Path?, + handle: String?, + options: MutableSet?, + vararg attrs: FileAttribute<*>? + ): SeekableByteChannel { + if (file is SafPath) { + return file.fileSystem.provider().newByteChannel(file, options, *attrs) + } + return super.openFile(subsystem, fileHandle, file, handle, options, *attrs) + } + }) + }.build()) keyAuth.deviceKey = device.certificate.publicKey @@ -110,6 +135,8 @@ internal class SimpleSftpServer { sshd.passwordAuthenticator = passwordAuth this.isInitialized = true + + this.sshd = sshd } fun start(): Boolean { @@ -119,8 +146,8 @@ internal class SimpleSftpServer { port = STARTPORT while (!isStarted) { try { - sshd.port = port - sshd.start() + sshd!!.port = port + sshd!!.start() isStarted = true } catch (e: IOException) { port++ @@ -139,7 +166,7 @@ internal class SimpleSftpServer { fun stop() { try { isStarted = false - sshd.stop(true) + sshd!!.stop(true) } catch (e: Exception) { Log.e("SFTP", "Exception while stopping the server", e) }