From 567a88ef3b62e2c410ba2e906b9b12040f3d4fd0 Mon Sep 17 00:00:00 2001 From: Jovi Hsu Date: Fri, 17 Nov 2023 02:59:24 +0000 Subject: [PATCH 1/3] Fix the high cpu usage when waiting server response --- src/config/version.rs | 4 ++-- src/model/packet.rs | 4 ++-- src/model/timeout.rs | 21 ++++++++++++++++++++- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/config/version.rs b/src/config/version.rs index dd253d0..a0e3905 100644 --- a/src/config/version.rs +++ b/src/config/version.rs @@ -28,7 +28,7 @@ where S: Read, { let mut buf = vec![0; 128]; - let timeout = Timeout::new(tm); + let mut timeout = Timeout::new(tm); loop { match stream.read(&mut buf) { Ok(i) => { @@ -38,7 +38,7 @@ where } Err(e) => { if let std::io::ErrorKind::WouldBlock = e.kind() { - timeout.test()?; + timeout.till_next_tick()?; continue; } else { return Err(e.into()); diff --git a/src/model/packet.rs b/src/model/packet.rs index fd65045..da57c8a 100644 --- a/src/model/packet.rs +++ b/src/model/packet.rs @@ -70,7 +70,7 @@ where } Err(e) => { if let std::io::ErrorKind::WouldBlock = e.kind() { - timeout.test()?; + timeout.till_next_tick()?; continue; } else { return Err(e.into()); @@ -117,7 +117,7 @@ where } Err(e) => { if let std::io::ErrorKind::WouldBlock = e.kind() { - timeout.test()?; + timeout.till_next_tick()?; continue; } else { return Err(e.into()); diff --git a/src/model/timeout.rs b/src/model/timeout.rs index 537f5e4..1d1fc99 100644 --- a/src/model/timeout.rs +++ b/src/model/timeout.rs @@ -1,9 +1,13 @@ use crate::{SshError, SshResult}; use std::time::{Duration, Instant}; +#[cfg(not(target_arch = "wasm32"))] +const NANOS_PER_SEC: u64 = 1_000_000_000; + pub(crate) struct Timeout { instant: Instant, timeout: Option, + wait_tick: u64, } impl Timeout { @@ -11,18 +15,33 @@ impl Timeout { Timeout { instant: Instant::now(), timeout, + wait_tick: 1, + } + } + + fn wait(&mut self) -> u64 { + #[cfg(not(target_arch = "wasm32"))] + { + let sleep_time = Duration::from_nanos(self.wait_tick); + std::thread::sleep(sleep_time); + if self.wait_tick < NANOS_PER_SEC { + self.wait_tick <<= 1; + } } + self.wait_tick } - pub fn test(&self) -> SshResult<()> { + pub fn till_next_tick(&mut self) -> SshResult<()> { if let Some(t) = self.timeout { if self.instant.elapsed() > t { tracing::error!("time out."); Err(SshError::TimeoutError) } else { + self.wait(); Ok(()) } } else { + self.wait(); Ok(()) } } From 29ae2d55a65446709bed39145ac62446066d9ae8 Mon Sep 17 00:00:00 2001 From: Jovi Hsu Date: Fri, 17 Nov 2023 03:23:40 +0000 Subject: [PATCH 2/3] According to rfc4253 section-4.2, remove the meaningless lines before ssh version agreement --- src/config/version.rs | 46 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/src/config/version.rs b/src/config/version.rs index a0e3905..516babc 100644 --- a/src/config/version.rs +++ b/src/config/version.rs @@ -23,18 +23,54 @@ impl Default for SshVersion { } } +/// + +// When the connection has been established, both sides MUST send an +// identification string. This identification string MUST be + +// SSH-protoversion-softwareversion SP comments CR LF + +// Since the protocol being defined in this set of documents is version +// 2.0, the 'protoversion' MUST be "2.0". The 'comments' string is +// OPTIONAL. If the 'comments' string is included, a 'space' character +// (denoted above as SP, ASCII 32) MUST separate the 'softwareversion' +// and 'comments' strings. The identification MUST be terminated by a +// single Carriage Return (CR) and a single Line Feed (LF) character +// (ASCII 13 and 10, respectively). fn read_version(stream: &mut S, tm: Option) -> SshResult> where S: Read, { - let mut buf = vec![0; 128]; + let mut ch = vec![0; 1]; + const LF: u8 = 0xa; + let crlf = vec![0xd, 0xa]; + let mut outbuf = vec![]; let mut timeout = Timeout::new(tm); loop { - match stream.read(&mut buf) { + match stream.read(&mut ch) { Ok(i) => { - // MY TO DO: To Skip the other lines - buf.truncate(i); - return Ok(buf); + if 0 == i { + // eof got, return + return Ok(outbuf); + } + + outbuf.extend_from_slice(&ch); + + if LF == ch[0] && outbuf.len() > 1 && outbuf.ends_with(&crlf) { + // The server MAY send other lines of data before sending the version + // string. Each line SHOULD be terminated by a Carriage Return and Line + // Feed. Such lines MUST NOT begin with "SSH-", and SHOULD be encoded + // in ISO-10646 UTF-8 [RFC3629] (language is not specified). Clients + // MUST be able to process such lines. Such lines MAY be silently + // ignored, or MAY be displayed to the client user. + if outbuf.len() < 4 || &outbuf[0..4] != SSH_MAGIC { + // skip other lines + // and start read for another line + outbuf.clear(); + continue; + } + return Ok(outbuf); + } } Err(e) => { if let std::io::ErrorKind::WouldBlock = e.kind() { From c875b05da38e65ac076883839056af922651ed38 Mon Sep 17 00:00:00 2001 From: Jovi Hsu Date: Fri, 17 Nov 2023 03:24:47 +0000 Subject: [PATCH 3/3] version 0.4.5 --- Cargo.toml | 2 +- changelog | 4 ++++ src/constant.rs | 2 +- src/lib.rs | 2 +- version | 2 +- 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 80d8906..7f26a64 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ssh-rs" -version = "0.4.4" +version = "0.4.5" edition = "2021" authors = [ "Gao Xiang Kang <1148118271@qq.com>", diff --git a/changelog b/changelog index a7ab4c9..f2be1f1 100644 --- a/changelog +++ b/changelog @@ -1,3 +1,7 @@ +v0.4.5 (2023-11-17) + 1. Fix the high cpu usage caused by non_block tcp + 2. Fix the failuer of version agreement if the server sends more than one lines + v0.4.4 (2023-11-15) 1. Remove some debug print 2. Fix the panic when connect to non-ssh servers diff --git a/src/constant.rs b/src/constant.rs index e5d32ea..46da5a6 100644 --- a/src/constant.rs +++ b/src/constant.rs @@ -1,5 +1,5 @@ /// The client version -pub(crate) const CLIENT_VERSION: &str = "SSH-2.0-SSH_RS-0.4.4"; +pub(crate) const CLIENT_VERSION: &str = "SSH-2.0-SSH_RS-0.4.5"; pub(crate) const SSH_MAGIC: &[u8] = b"SSH-"; /// The constant strings that used for ssh communication diff --git a/src/lib.rs b/src/lib.rs index 0f4718b..e119c2c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ //! Dependencies //! ```toml -//! ssh-rs = "0.4.4" +//! ssh-rs = "0.4.5" //! ``` //! //!Rust implementation of ssh2.0 client. diff --git a/version b/version index 6f2743d..0bfccb0 100644 --- a/version +++ b/version @@ -1 +1 @@ -0.4.4 +0.4.5