diff --git a/services/modals/src/lib.rs b/services/modals/src/lib.rs index 506f2d45f..bfe6f9313 100644 --- a/services/modals/src/lib.rs +++ b/services/modals/src/lib.rs @@ -484,12 +484,19 @@ impl Modals { /// frequent updates. For example, instead of once every iteration of a loop, once every ten /// iterations. This will improve performance of the code and reduce UI churn as well. If this is not /// possible, you can add a sleep by doing something like the code below. This will reduce the rate at - /// which your loop runs, as well as at which the UI updates. Example: - /// `std::thread::sleep(std::time::Duration::from_millis(100));` - /// + /// which your loop runs, as well as at which the UI updates. + /// ``` + /// std::thread::sleep(std::time::Duration::from_millis(100)); // This comment needed to pass formatting checks + /// ``` /// - An alternative "softer" solution is to call yield. This will cause the producer to yield its time - /// slice to other processes in the OS, which can give the progress bar a chance to catch up. Example: - /// `xous::yield_slice();` + /// slice to other processes in the OS, which can give the progress bar a chance to catch up. + /// ``` + /// xous::yield_slice(); // This comment needed to pass formatting checks + /// ``` + /// The comments above are necessary because rustfmt puts trailing whitespace after the code if there + /// isn't a comment. We have a requirement to have no trailing whitespace *and* for code to be + /// auto-formatted. So, the dummy comment is there simply to resolve the two conflicting requirements + /// in the face of a buggy rust format (as of 1.81). /// /// # Example /// ``` diff --git a/services/shellchat/Cargo.toml b/services/shellchat/Cargo.toml index 08b650350..e3fe9a60d 100644 --- a/services/shellchat/Cargo.toml +++ b/services/shellchat/Cargo.toml @@ -153,4 +153,5 @@ rand-api = [] locktests = [ ] # for debugging some specific `std` tests cherry-picked out of the test suite simple-tls = ["rustls", "webpki-roots"] +nettype = [] # takes a file from a URL and emits it as keystrokes default = [] # "debugprint" diff --git a/services/shellchat/src/cmds/usb.rs b/services/shellchat/src/cmds/usb.rs index 40cf3b780..16462a999 100644 --- a/services/shellchat/src/cmds/usb.rs +++ b/services/shellchat/src/cmds/usb.rs @@ -151,6 +151,64 @@ impl<'a> ShellCmdApi<'a> for Usb { write!(ret, "USB debug port unlocked: portions of the device are readable via USB!") .unwrap(); } + #[cfg(feature = "nettype")] + "nettype" => { + use std::io::{Read, Write}; + use std::net::TcpStream; + use std::time::Duration; + if let Some(url) = tokens.next() { + match url.split_once('/') { + Some((host, path)) => match TcpStream::connect((host, 80)) { + Ok(mut stream) => { + stream.set_read_timeout(Some(Duration::from_millis(10_000))).unwrap(); + stream.set_write_timeout(Some(Duration::from_millis(10_000))).unwrap(); + log::info!("sending GET request"); + match write!(stream, "GET /{} HTTP/1.1\r\n", path) { + Ok(_) => log::trace!("sent GET"), + Err(e) => { + log::error!("GET err {:?}", e); + write!(ret, "Error sending GET: {:?}", e).unwrap(); + } + } + write!( + stream, + "Host: {}\r\nAccept: */*\r\nUser-Agent: Precursor/0.9.16\r\n", + host + ) + .expect("stream error"); + write!(stream, "Connection: close\r\n").expect("stream error"); + write!(stream, "\r\n").expect("stream error"); + log::info!("fetching response...."); + let mut buf = [0u8; 4096]; + match stream.read(&mut buf) { + Ok(len) => { + let s = std::string::String::from_utf8_lossy( + &buf[..len.min(buf.len())], + ); + let mut parts = s.splitn(2, "\r\n\r\n"); + let _header = parts.next().unwrap_or(""); + let body = parts.next().unwrap_or(""); + match self.usb_dev.send_str(&body) { + Ok(n) => write!(ret, "Sent {} chars", n).unwrap(), + Err(_e) => { + write!(ret, "Can't send: are we connected to a host?") + .unwrap() + } + } + } + Err(e) => { + write!(ret, "Didn't get response from host: {:?}", e).unwrap() + } + } + } + Err(e) => write!(ret, "Couldn't connect to {}:80: {:?}", host, e).unwrap(), + }, + _ => write!(ret, "Usage: nettype bunniefoo.com/bunnie/test.txt").unwrap(), + } + } else { + write!(ret, "Usage: nettype bunniefoo.com/bunnie/test.txt").unwrap(); + } + } _ => { write!(ret, "{}", helpstring).unwrap(); }