Skip to content

Commit

Permalink
Add wasefire applet-rpc command (#517)
Browse files Browse the repository at this point in the history
  • Loading branch information
ia0 authored Jun 26, 2024
1 parent 40ba802 commit 9c10462
Show file tree
Hide file tree
Showing 15 changed files with 600 additions and 28 deletions.
2 changes: 1 addition & 1 deletion crates/cli-tools/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

## 0.1.0-git

<!-- Increment to skip CHANGELOG.md test: 12 -->
<!-- Increment to skip CHANGELOG.md test: 13 -->
175 changes: 172 additions & 3 deletions crates/cli-tools/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions crates/cli-tools/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,16 @@ categories = ["command-line-utilities", "embedded", "wasm"]
anyhow = { version = "1.0.86", default-features = false, features = ["std"] }
cargo_metadata = { version = "0.18.1", default-features = false }
clap = { version = "4.5.4", default-features = false, features = ["derive", "std"] }
humantime = { version = "2.1.0", default-features = false }
rusb = { version = "0.9.4", default-features = false }
serde = { version = "1.0.202", default-features = false, features = ["derive"] }
toml = { version = "0.8.13", default-features = false, features = ["display", "parse"] }
wasefire-protocol = { version = "0.1.0-git", path = "../protocol" }

[dependencies.wasefire-protocol-usb]
version = "0.1.0-git"
path = "../protocol-usb"
features = ["host", "log"]

[lints]
clippy.unit-arg = "allow"
Expand Down
56 changes: 55 additions & 1 deletion crates/cli-tools/src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,67 @@
use std::fmt::Display;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::time::Duration;

use anyhow::{ensure, Result};
use anyhow::{bail, ensure, Result};
use cargo_metadata::{Metadata, MetadataCommand};
use clap::{ValueEnum, ValueHint};
use rusb::UsbContext;
use wasefire_protocol::{applet, AppletRequest, AppletResponse};
use wasefire_protocol_usb::Connection;

use crate::{cmd, fs};

/// Calls an RPC to an applet on a platform.
#[derive(clap::Args)]
pub struct AppletRpc {
/// Applet identifier in the platform.
applet: Option<String>,

/// Reads the request from this file instead of standard input.
#[arg(long, value_hint = ValueHint::FilePath)]
input: Option<PathBuf>,

/// Writes the response to this file instead of standard output.
#[arg(long, value_hint = ValueHint::AnyPath)]
output: Option<PathBuf>,

/// Timeout to send the request and try receiving the response.
#[arg(long, value_parser = humantime::parse_duration, default_value = "1s")]
timeout: Duration,

/// Number of retries to receive a response.
#[arg(long, default_value = "3")]
retries: usize,
}

impl AppletRpc {
pub fn run<T: UsbContext>(self, connection: &Connection<T>) -> Result<()> {
let AppletRpc { applet, input, output, timeout, retries } = self;
let applet_id = match applet {
Some(_) => bail!("applet identifiers are not supported yet"),
None => applet::AppletId,
};
let input = match input {
Some(path) => fs::read(path)?,
None => fs::read_stdin()?,
};
let request = applet::Request { applet_id, request: &input };
connection.call::<AppletRequest>(request, timeout)?.get();
for _ in 0 .. retries {
let response = connection.call::<AppletResponse>(applet_id, timeout)?;
if let Some(response) = response.get().response {
match output {
Some(path) => fs::write(path, response)?,
None => fs::write_stdout(response)?,
}
return Ok(());
}
}
bail!("did not receive a response after {retries} retries");
}
}

/// Creates a new Rust applet project.
#[derive(clap::Args)]
pub struct RustAppletNew {
Expand Down
14 changes: 13 additions & 1 deletion crates/cli-tools/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
//! Wrappers around `std::fs` with descriptive errors.

use std::fs::Metadata;
use std::io::ErrorKind;
use std::io::{ErrorKind, Read, Write};
use std::path::{Component, Path, PathBuf};

use anyhow::{Context, Result};
Expand Down Expand Up @@ -113,6 +113,12 @@ pub fn read_toml<T: DeserializeOwned>(path: impl AsRef<Path>) -> Result<T> {
toml::from_str(&data).with_context(|| format!("parsing {name}"))
}

pub fn read_stdin() -> Result<Vec<u8>> {
let mut data = Vec::new();
std::io::stdin().read_to_end(&mut data).context("reading from stdin")?;
Ok(data)
}

pub fn remove_file(path: impl AsRef<Path>) -> Result<()> {
let name = path.as_ref().display();
debug!("rm {name:?}");
Expand Down Expand Up @@ -142,6 +148,12 @@ pub fn write_toml<T: Serialize>(path: impl AsRef<Path>, contents: &T) -> Result<
Ok(())
}

pub fn write_stdout(contents: impl AsRef<[u8]>) -> Result<()> {
let contents = contents.as_ref();
std::io::stdout().write_all(contents).context("writing to stdout")?;
Ok(())
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
2 changes: 2 additions & 0 deletions crates/cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

### Minor

- Implement `applet-rpc` command
- Add `--serial` and `WASEFIRE_SERIAL` to select the platform
- Implement `platform-list` command
- Support creating, building, and testing a Rust applet
- Support generating a shell completion file
Expand Down
Loading

0 comments on commit 9c10462

Please sign in to comment.