Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version 0.4.5 #89

Merged
merged 3 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -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>",
Expand Down
4 changes: 4 additions & 0 deletions changelog
Original file line number Diff line number Diff line change
@@ -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
Expand Down
50 changes: 43 additions & 7 deletions src/config/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,58 @@ impl Default for SshVersion {
}
}

/// <https://www.rfc-editor.org/rfc/rfc4253#section-4.2>

// 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<S>(stream: &mut S, tm: Option<Duration>) -> SshResult<Vec<u8>>
where
S: Read,
{
let mut buf = vec![0; 128];
let timeout = Timeout::new(tm);
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() {
timeout.test()?;
timeout.till_next_tick()?;
continue;
} else {
return Err(e.into());
Expand Down
2 changes: 1 addition & 1 deletion src/constant.rs
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Dependencies
//! ```toml
//! ssh-rs = "0.4.4"
//! ssh-rs = "0.4.5"
//! ```
//!
//!Rust implementation of ssh2.0 client.
Expand Down
4 changes: 2 additions & 2 deletions src/model/packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down Expand Up @@ -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());
Expand Down
21 changes: 20 additions & 1 deletion src/model/timeout.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,47 @@
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<Duration>,
wait_tick: u64,
}

impl Timeout {
pub fn new(timeout: Option<Duration>) -> Self {
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(())
}
}
Expand Down
2 changes: 1 addition & 1 deletion version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.4.4
0.4.5