Skip to content
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
1,925 changes: 1,662 additions & 263 deletions Cargo.lock

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ description = "Simple remote devboard control software (non-interactive CLI)"
readme = "README.md"
repository = "https://github.com/linux-msm/sk8brd"
categories = ["command-line-utilities"]
publish = false # TODO
publish = false # TODO

[badges]
maintenance = { status = "actively-developed" }
Expand All @@ -19,11 +19,11 @@ path = "src/main.rs"

[dependencies]
anyhow = "1.0"
clap = { version = "4.5.4", features = ["derive"] }
colored = "2.1.0"
crossterm = "0.27.0"
clap = { version = "4.5.31", features = ["derive"] }
colored = "3.0.0"
crossterm = "0.28.1"
sk8brd-proto = { path = "../proto/", features = ["ssh"] }
os_pipe = "1.1.5"
serde = { version = "^1.0.198", features = ["derive"] }
ssh2 = "^0.9.4"
tokio = { version = "^1.37.0", features = ["full"] }
os_pipe = "1.2.1"
russh = "0.50.4"
serde = { version = "1.0.218", features = ["derive"] }
tokio = { version = "1.43.0", features = ["full"] }
48 changes: 32 additions & 16 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
use anyhow::Context;
use clap::Parser;
use colored::Colorize;
use sk8brd::ssh::{ssh_connect, ssh_disconnect, ssh_get_chan, SSH_BUFFER_SIZE};
use russh::client::Msg;
use sk8brd::ssh::{ssh_connect, SSH_BUFFER_SIZE};
use sk8brd::{
console_print, parse_recv_msg, print_string_msg, select_brd, send_ack, send_image, todo,
Sk8brdMsgs, CDBA_SERVER_BIN_NAME, MSG_HDR_SIZE,
};
use std::fs;
use std::io::{stdout, Read, Write};
use std::io::{stdout, Write};
use std::sync::Arc;
use std::time::{Duration, SystemTime};
use tokio::io::AsyncReadExt;
use tokio::sync::Mutex;

#[derive(Parser, Debug)]
Expand Down Expand Up @@ -48,42 +51,55 @@ async fn main() -> anyhow::Result<()> {

println!("sk8brd-cli {}", env!("CARGO_PKG_VERSION"));

let mut sess = ssh_connect(args.farm, args.port, args.user).await?;
sess.set_blocking(true);
let mut chan = ssh_get_chan(&mut sess, CDBA_SERVER_BIN_NAME).await?;
let chan = Arc::new(Mutex::new(
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only reason I can see for this being an Arc<Mutex<Channel>> and not just a Channel is because ssh::into_streams() below takes a Arc<Mutex<>>, presumably so that one could share the chan with the close at the async thread?

I think it would be cleaner if sk8brd provided an interface that abstracts away the ssh_connect() and just returns the three streams.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm merging this as-is, we can make incremental improvements

ssh_connect(&format!("{}:{}", args.farm, args.port), args.user).await?,
));
(*chan.lock().await)
.exec(true, CDBA_SERVER_BIN_NAME)
.await
.with_context(|| format!("Couldn't execute {CDBA_SERVER_BIN_NAME} on remote server"))?;

let mut server_stdin = Arc::new(Mutex::new((*chan.lock().await).make_writer()));
let (server_stdout, server_stderr) = sk8brd::ssh::into_streams::<Msg>(chan).await;
let server_stdout = Arc::new(Mutex::new(server_stdout));
let server_stderr = Arc::new(Mutex::new(server_stderr));

if args.board.is_empty() {
send_ack(&mut chan, Sk8brdMsgs::MsgListDevices).await?;
send_ack(&mut server_stdin, Sk8brdMsgs::MsgListDevices).await?;
} else {
select_brd(&mut chan, &args.board).await?;
select_brd(&mut server_stdin, &args.board).await?;
}

// Msg handler
// Read the message header first
while time.elapsed()? < Duration::from_secs(args.timeout) {
// Stream of "blue text" - status updates from the server
sess.set_blocking(false);
if let Ok(bytes_read) = (*chan.lock().await).stderr().read(&mut buf) {
if let Ok(bytes_read) = (*server_stderr.lock().await).read(&mut buf).await {
let s = String::from_utf8_lossy(&buf[..bytes_read]);
print!(
"{}\r",
s.split('\n').collect::<Vec<_>>().join("\r\n").blue()
);
stdout().flush()?;
}
sess.set_blocking(true);

if (*chan.lock().await).read_exact(&mut hdr_buf).is_ok() {
if (*server_stdout.lock().await)
.read_exact(&mut hdr_buf)
.await
.is_ok()
{
let msg = parse_recv_msg(&hdr_buf);
let mut msgbuf = vec![0u8; msg.len as usize];

// Now read the actual data...
(*chan.lock().await).read_exact(&mut msgbuf)?;
(*server_stderr.lock().await)
.read_exact(&mut msgbuf)
.await?;

// ..and process it
match msg.r#type.try_into() {
Ok(Sk8brdMsgs::MsgSelectBoard) => {
send_ack(&mut chan, Sk8brdMsgs::MsgPowerOn).await?
send_ack(&mut server_stdin, Sk8brdMsgs::MsgPowerOn).await?
}
Ok(Sk8brdMsgs::MsgConsole) => {
if args.verbose {
Expand All @@ -96,7 +112,7 @@ async fn main() -> anyhow::Result<()> {
}
Ok(Sk8brdMsgs::MsgFastbootPresent) => {
if !msgbuf.is_empty() && msgbuf[0] != 0 {
send_image(&mut chan, &fastboot_image, &quit).await?
send_image(&mut server_stdin, &fastboot_image, &quit).await?
}
}
Ok(Sk8brdMsgs::MsgFastbootDownload) => (),
Expand All @@ -115,9 +131,9 @@ async fn main() -> anyhow::Result<()> {
}

// Power off the board on goodbye
send_ack(&mut chan, Sk8brdMsgs::MsgPowerOff).await?;
send_ack(&mut server_stdin, Sk8brdMsgs::MsgPowerOff).await?;

ssh_disconnect(&mut sess).await?;
// ssh_disconnect(&mut sess).await?;

println!("\nGoodbye");
Ok(())
Expand Down
16 changes: 8 additions & 8 deletions client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ path = "src/main.rs"

[dependencies]
anyhow = "1.0"
clap = { version = "4.5.4", features = ["derive"] }
colored = "2.1.0"
crossterm = "0.27.0"
sk8brd-proto = { version = "^0.1.0", path = "../proto", features = ["ssh"] }
os_pipe = "1.1.5"
serde = { version = "^1.0.198", features = ["derive"] }
ssh2 = "^0.9.4"
tokio = { version = "^1.37.0", features = ["full"] }
clap = { version = "4.5.31", features = ["derive"] }
colored = "3.0.0"
crossterm = "0.28.1"
sk8brd-proto = { path = "../proto", features = ["ssh"] }
os_pipe = "1.2.1"
serde = { version = "1.0.218", features = ["derive"] }
tokio = { version = "1.43.0", features = ["full"] }
russh = "0.50.4"
59 changes: 40 additions & 19 deletions client/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
use anyhow::Context;
use clap::Parser;
use colored::Colorize;
use sk8brd::ssh::{ssh_connect, ssh_disconnect, ssh_get_chan, SSH_BUFFER_SIZE};
use russh::client::Msg;
use sk8brd::ssh::{ssh_connect, SSH_BUFFER_SIZE};
use sk8brd::{
console_print, parse_recv_msg, print_string_msg, select_brd, send_ack, send_break,
send_console, send_image, send_msg, todo, Sk8brdMsgs, CDBA_SERVER_BIN_NAME, MSG_HDR_SIZE,
};
use std::fs;
use std::io::{stdout, Read, Write};
use std::sync::Arc;
use tokio::io::{AsyncReadExt, AsyncWrite};
use tokio::sync::Mutex;

macro_rules! get_arc {
Expand Down Expand Up @@ -42,7 +45,7 @@ async fn handle_keypress(
c: char,
quit: &mut Arc<Mutex<bool>>,
special: &mut bool,
message_sink: &mut Arc<Mutex<impl Write>>,
message_sink: &mut Arc<Mutex<impl AsyncWrite + Unpin>>,
) {
if *special {
*special = false;
Expand Down Expand Up @@ -86,37 +89,53 @@ async fn main() -> anyhow::Result<()> {

println!("sk8brd {}", env!("CARGO_PKG_VERSION"));

let mut sess = ssh_connect(args.farm, args.port, args.user).await?;
let mut chan = ssh_get_chan(&mut sess, CDBA_SERVER_BIN_NAME).await?;
sess.set_blocking(false);
let chan = Arc::new(Mutex::new(
ssh_connect(&format!("{}:{}", args.farm, args.port), args.user).await?,
));
get_arc!(chan)
.exec(true, CDBA_SERVER_BIN_NAME)
.await
.with_context(|| format!("Couldn't execute {CDBA_SERVER_BIN_NAME} on remote server"))?;

send_ack(&mut chan, Sk8brdMsgs::MsgListDevices).await?;
select_brd(&mut chan, &args.board).await?;
let mut server_stdin = Arc::new(Mutex::new(get_arc!(chan).make_writer()));

let (server_stdout, server_stderr) = sk8brd::ssh::into_streams::<Msg>(chan).await;
let server_stdout = Arc::new(Mutex::new(server_stdout));
let server_stderr = Arc::new(Mutex::new(server_stderr));

send_ack(&mut server_stdin, Sk8brdMsgs::MsgListDevices).await?;
select_brd(&mut server_stdin, &args.board).await?;
if args.power_cycle {
println!("Powering off the board first");
send_ack(&mut chan, Sk8brdMsgs::MsgPowerOff).await?;
send_ack(&mut server_stdin, Sk8brdMsgs::MsgPowerOff).await?;
}

crossterm::terminal::enable_raw_mode()?;

let mut quit2 = Arc::clone(&quit);
let mut chan2 = Arc::clone(&chan);
let mut server_stdin2 = Arc::clone(&server_stdin);
let stdin_handler = tokio::spawn(async move {
let mut stdin = os_pipe::dup_stdin().expect("Couldn't dup stdin");
let mut ctrl_a_pressed = false;

while !*get_arc!(quit2) {
if let Ok(len) = stdin.read(&mut key_buf) {
for c in key_buf[0..len].iter() {
handle_keypress(*c as char, &mut quit2, &mut ctrl_a_pressed, &mut chan2).await;
handle_keypress(
*c as char,
&mut quit2,
&mut ctrl_a_pressed,
&mut server_stdin2,
)
.await;
}
};
}
});

while !*get_arc!(quit) {
// Stream of "blue text" - status updates from the server
if let Ok(bytes_read) = (*get_arc!(chan)).stderr().read(&mut buf) {
if let Ok(bytes_read) = (*get_arc!(server_stderr)).read(&mut buf).await {
let s = String::from_utf8_lossy(&buf[..bytes_read]);
print!(
"{}\r",
Expand All @@ -127,26 +146,29 @@ async fn main() -> anyhow::Result<()> {

// Msg handler
// Read the message header first
if (*get_arc!(chan)).read_exact(&mut hdr_buf).is_ok() {
sess.set_blocking(true);
if (*get_arc!(server_stdout))
.read_exact(&mut hdr_buf)
.await
.is_ok()
{
let msg = parse_recv_msg(&hdr_buf);
let mut msgbuf = vec![0u8; msg.len as usize];

// Now read the actual data...
(*get_arc!(chan)).read_exact(&mut msgbuf)?;
(*get_arc!(server_stdout)).read_exact(&mut msgbuf).await?;

// ..and process it
match msg.r#type.try_into() {
Ok(Sk8brdMsgs::MsgSelectBoard) => {
send_msg(&mut chan, Sk8brdMsgs::MsgPowerOn, &[]).await?
send_msg(&mut server_stdin, Sk8brdMsgs::MsgPowerOn, &[]).await?
}
Ok(Sk8brdMsgs::MsgConsole) => console_print(&msgbuf).await,
Ok(Sk8brdMsgs::MsgHardReset) => todo!("MsgHardReset is unused"),
Ok(Sk8brdMsgs::MsgPowerOn) => (),
Ok(Sk8brdMsgs::MsgPowerOff) => (),
Ok(Sk8brdMsgs::MsgFastbootPresent) => {
if !msgbuf.is_empty() && msgbuf[0] != 0 {
send_image(&mut chan, &fastboot_image, &quit).await?
send_image(&mut server_stdin, &fastboot_image, &quit).await?
}
}
Ok(Sk8brdMsgs::MsgFastbootDownload) => (),
Expand All @@ -163,7 +185,6 @@ async fn main() -> anyhow::Result<()> {
Ok(m) => todo!("{m:?} is unimplemented, skipping.."),
Err(e) => todo!("Received unknown/invalid message: `{e}`"),
};
sess.set_blocking(false);
}
}

Expand All @@ -174,9 +195,9 @@ async fn main() -> anyhow::Result<()> {
crossterm::terminal::disable_raw_mode()?;

// Power off the board on goodbye
send_ack(&mut chan, Sk8brdMsgs::MsgPowerOff).await?;
send_ack(&mut server_stdin, Sk8brdMsgs::MsgPowerOff).await?;

ssh_disconnect(&mut sess).await?;
// ssh_disconnect(&mut sess).await?;

println!("\nGoodbye");
Ok(())
Expand Down
19 changes: 11 additions & 8 deletions proto/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "sk8brd-proto"
version = "0.1.0"
edition = "2021"
edition = "2024"
authors = ["Konrad Dybcio <konradybcio@kernel.org>"]
license = "BSD-3-Clause"
description = "Simple remote devboard control software"
Expand All @@ -21,10 +21,13 @@ ssh = []

[dependencies]
anyhow = "1.0"
clap = { version = "4.5.4", features = ["derive"] }
colored = "2.1.0"
crossterm = "0.27.0"
os_pipe = "1.1.5"
serde = { version = "^1.0.198", features = ["derive"] }
ssh2 = "^0.9.4"
tokio = { version = "^1.37.0", features = ["full"] }
async-trait = "0.1.87"
asynchronous-codec = "0.7.0"
clap = { version = "4.5.31", features = ["derive"] }
colored = "3.0.0"
crossterm = "0.28.1"
os_pipe = "1.2.1"
russh = "0.50.4"
serde = { version = "1.0.218", features = ["derive"] }
tokio = { version = "1.43.0", features = ["full"] }
use = "0.0.1-pre.0"
Loading
Loading