diff --git a/embassy/Cargo.toml b/embassy/Cargo.toml index b78c034120710c8ed23c605eb6d250e4aa3ffb56..864b04053bfb85e1033205187f8d815ce6cd79e5 100644 --- a/embassy/Cargo.toml +++ b/embassy/Cargo.toml @@ -5,6 +5,8 @@ edition = "2021" [dependencies] embassy-sync = { version = "0.1.0" } +embassy-net = { version = "0.1.0" } +embassy-futures = { version = "0.1.0" } pin-utils = { version = "0.1" } sunset = { path = "../" } diff --git a/embassy/README.md b/embassy/README.md index 20bb87214bbd2a29747c771527f565cafb5a66ce..8675d383bbe863279cfdf8c789d47bc3fc298fdf 100644 --- a/embassy/README.md +++ b/embassy/README.md @@ -1,10 +1,11 @@ # Toolchain -Embassy requires Rust nightly, often with a specific version. [`rust-toolchain.toml`] records a known-good version. +Embassy requires Rust nightly, often with a specific version. +[`rust-toolchain.toml`](rust-toolchain.toml) records a known-good version. # Demos -[`demos/`] has some examples. These are separate crates since they have fairly distinct dependencies. +[`demos/`](demos/) has some examples. These are separate crates since they have fairly distinct dependencies. ## `picow` diff --git a/embassy/demos/picow/Cargo.lock b/embassy/demos/picow/Cargo.lock index 6ff60eb49e881c63e7a183506ab4368084176fbc..6ead6024d99c3c2d1be5650651d069629c3bc769 100644 --- a/embassy/demos/picow/Cargo.lock +++ b/embassy/demos/picow/Cargo.lock @@ -1354,8 +1354,11 @@ dependencies = [ name = "sunset-embassy" version = "0.2.0-alpha" dependencies = [ + "embassy-futures", + "embassy-net", "embassy-sync 0.1.0", "log", + "pin-utils", "sunset", ] diff --git a/embassy/demos/picow/src/main.rs b/embassy/demos/picow/src/main.rs index baea62a741d5480b5d7fba1cffb9eb69068e02a6..baa0bf184da3f7e9bb9ff70f58f438d64dc0533a 100644 --- a/embassy/demos/picow/src/main.rs +++ b/embassy/demos/picow/src/main.rs @@ -12,7 +12,7 @@ use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_net::tcp::TcpSocket; use embassy_net::{Stack, StackResources}; use embassy_rp::gpio::{Flex, Level, Output}; -use embassy_futures::join::join3; +use embassy_futures::join::join; use embassy_rp::peripherals::{PIN_23, PIN_24, PIN_25, PIN_29}; use embedded_hal_async::spi::{ExclusiveDevice, SpiBusFlush, SpiBusRead, SpiBusWrite}; use embedded_io::asynch::{Read, Write}; @@ -45,30 +45,6 @@ macro_rules! singleton { }}; } -// fn run() -> sunset::Result<()> { -// let mut x = [0u8; 500]; - -// let mut inbuf = [0u8; 1000]; -// let mut outbuf = [0u8; 1000]; -// let mut runner = sunset::Runner::new_server(&mut inbuf, &mut outbuf)?; -// let mut cli = SSHClient {}; -// let mut cli = sunset::Behaviour::new_client(&mut cli); - -// let mut pollctx = Context::from_waker(noop_waker_ref()); - -// runner.input(&x)?; -// let l = runner.progress(&mut cli); -// pin_mut!(l); -// let _ = l.poll(&mut pollctx); -// // runner.output(&mut x).unwrap(); - -// // tx.write(b'x').unwrap(); -// // write!(tx, "{}", x[0]); - -// Ok(()) -// } - - #[embassy_executor::task] async fn net_task(stack: &'static Stack<cyw43::NetDevice<'static>>) -> ! { stack.run().await @@ -114,8 +90,8 @@ async fn main(spawner: Spawner) { let net_device = control.init(clm).await; //control.join_open(env!("WIFI_NETWORK")).await; - // control.join_wpa2(env!("WIFI_NETWORK"), env!("WIFI_PASSWORD")).await; - control.join_wpa2("WIFI_NETWORK", "WIFI_PASSWORD").await; + control.join_wpa2(env!("WIFI_NETWORK"), env!("WIFI_PASSWORD")).await; + //control.join_wpa2("WIFI_NETWORK", "WIFI_PASSWORD").await; let config = embassy_net::ConfigStrategy::Dhcp; //let config = embassy_net::ConfigStrategy::Static(embassy_net::Config { @@ -166,32 +142,32 @@ async fn listener(stack: &'static Stack<cyw43::NetDevice<'static>>) -> ! { } struct DemoServer { - // keys: Vec<SignKey>, + keys: [SignKey; 1], sess: Option<u32>, want_shell: bool, shell_started: bool, + + notify: Signal<NoopRawMutex, ()>, } impl DemoServer { fn new() -> Result<Self> { - // let keys = keyfiles.iter().map(|f| { - // read_key(f).with_context(|| format!("loading key {f}")) - // }).collect::<Result<Vec<SignKey>>>()?; + let keys = [SignKey::generate(KeyType::Ed25519)?]; Ok(Self { sess: None, - // keys, + keys, want_shell: false, shell_started: false, + notify: Signal::new(), }) } } impl ServBehaviour for DemoServer { fn hostkeys(&mut self) -> BhResult<&[SignKey]> { - todo!() - // Ok(&self.keys) + Ok(&self.keys) } @@ -203,6 +179,12 @@ impl ServBehaviour for DemoServer { true } + fn auth_unchallenged(&mut self, username: TextString) -> bool { + let u = username.as_str().unwrap_or("mystery user"); + info!("Allowing auth for user {}", u); + true + } + fn auth_password(&mut self, user: TextString, password: TextString) -> bool { user.as_str().unwrap_or("") == "matt" && password.as_str().unwrap_or("") == "pw" } @@ -242,91 +224,24 @@ impl ServBehaviour for DemoServer { } async fn session(socket: &mut TcpSocket<'_>) -> sunset::Result<()> { - let mut app = DemoServer::new()?; - - let mut ssh_rxbuf = [0; 1024]; - let mut ssh_txbuf = [0; 1024]; - let serv = SSHServer::new(&mut ssh_rxbuf, &mut ssh_txbuf, &mut app)?; - let serv = &serv; - - let app = Mutex::<NoopRawMutex, _>::new(app); - - let (mut rsock, mut wsock) = socket.split(); - - let tx = async { - loop { - // TODO: make sunset read directly from socket, no intermediate buffer. - let mut buf = [0; 1024]; - let l = serv.read(&mut buf).await?; - let mut buf = &buf[..l]; - while buf.len() > 0 { - let n = wsock.write(buf).await.expect("TODO handle write error"); - buf = &buf[n..]; - } - } - #[allow(unreachable_code)] - Ok::<_, sunset::Error>(()) - }; - - let rx = async { - loop { - // TODO: make sunset read directly from socket, no intermediate buffer. - let mut buf = [0; 1024]; - let l = rsock.read(&mut buf).await.expect("TODO handle read error"); - let mut buf = &buf[..l]; - while buf.len() > 0 { - let n = serv.write(&buf).await?; - buf = &buf[n..]; - } - } - #[allow(unreachable_code)] - Ok::<_, sunset::Error>(()) - }; - - let prog = async { - loop { - serv.progress(&app).await?; - } - #[allow(unreachable_code)] - Ok::<_, sunset::Error>(()) - }; - join3(rx, tx, prog).await; - - Ok(()) -} + let mut app = DemoServer::new()?; + + let mut ssh_rxbuf = [0; 2000]; + let mut ssh_txbuf = [0; 2000]; + let serv = SSHServer::new(&mut ssh_rxbuf, &mut ssh_txbuf, &mut app)?; + let serv = &serv; + + let app = Mutex::<NoopRawMutex, _>::new(app); - // info!("Received connection from {:?}", socket.remote_endpoint()); - - // #[embassy_executor::task] - // async fn from_wir(stack: &'static Stack<cyw43::NetDevice<'static>>) -> ! { - // stack.run().await - // } - - // spawner.spawn(sunset_task(runner)).unwrap(); - - // run().unwrap(); - - // loop { - // let n = match socket.read(&mut buf).await { - // Ok(0) => { - // warn!("read EOF"); - // break; - // } - // Ok(n) => n, - // Err(e) => { - // warn!("read error: {:?}", e); - // break; - // } - // }; - - // info!("rxd {:02x}", &buf[..n]); - - // match socket.write(&buf[..n]).await { - // Ok(_sz) => {} - // Err(e) => { - // warn!("write error: {:?}", e); - // break; - // } - // }; - // } + let run = serv.run(socket, &app); + let session = async { + loop { + } + }; + + // TODO: handle results + join(run, session).await; + + Ok(()) +} diff --git a/embassy/demos/std/Cargo.lock b/embassy/demos/std/Cargo.lock index cb24dc96580f9327d6d086b51d3291f3652f8ac6..8f17a036c15d4ff7a54be84ae14daf81bc3983a0 100644 --- a/embassy/demos/std/Cargo.lock +++ b/embassy/demos/std/Cargo.lock @@ -1288,6 +1288,8 @@ dependencies = [ name = "sunset-embassy" version = "0.2.0-alpha" dependencies = [ + "embassy-futures", + "embassy-net", "embassy-sync 0.1.0", "log", "pin-utils", diff --git a/embassy/demos/std/src/main.rs b/embassy/demos/std/src/main.rs index 96841eb61d884ba48f9ae7b80ee841c698ab77d2..abd740b32bed2ceebd715a32974d1eac850570ef 100644 --- a/embassy/demos/std/src/main.rs +++ b/embassy/demos/std/src/main.rs @@ -43,29 +43,6 @@ macro_rules! singleton { }}; } -// fn run() -> sunset::Result<()> { -// let mut x = [0u8; 500]; - -// let mut inbuf = [0u8; 1000]; -// let mut outbuf = [0u8; 1000]; -// let mut runner = sunset::Runner::new_server(&mut inbuf, &mut outbuf)?; -// let mut cli = SSHClient {}; -// let mut cli = sunset::Behaviour::new_client(&mut cli); - -// let mut pollctx = Context::from_waker(noop_waker_ref()); - -// runner.input(&x)?; -// let l = runner.progress(&mut cli); -// pin_mut!(l); -// let _ = l.poll(&mut pollctx); -// // runner.output(&mut x).unwrap(); - -// // tx.write(b'x').unwrap(); -// // write!(tx, "{}", x[0]); - -// Ok(()) -// } - #[embassy_executor::task] async fn net_task(stack: &'static Stack<TunTapDevice>) -> ! { stack.run().await @@ -82,7 +59,6 @@ async fn main_task(spawner: Spawner) { // Init network device let device = TunTapDevice::new(opt_tap0).unwrap(); - let seed = OsRng.next_u64(); // Init network stack @@ -126,7 +102,7 @@ async fn listener(stack: &'static Stack<TunTapDevice>) -> ! { } struct DemoServer { - // keys: Vec<SignKey>, + keys: [SignKey; 1], sess: Option<u32>, want_shell: bool, @@ -135,13 +111,12 @@ struct DemoServer { impl DemoServer { fn new() -> Result<Self> { - // let keys = keyfiles.iter().map(|f| { - // read_key(f).with_context(|| format!("loading key {f}")) - // }).collect::<Result<Vec<SignKey>>>()?; + + let keys = [SignKey::generate(KeyType::Ed25519)?]; Ok(Self { sess: None, - // keys, + keys, want_shell: false, shell_started: false, }) @@ -150,8 +125,7 @@ impl DemoServer { impl ServBehaviour for DemoServer { fn hostkeys(&mut self) -> BhResult<&[SignKey]> { - todo!("hostkeys()") - // Ok(&self.keys) + Ok(&self.keys) } @@ -160,6 +134,11 @@ impl ServBehaviour for DemoServer { } fn have_auth_pubkey(&self, user: TextString) -> bool { + false + } + + fn auth_unchallenged(&mut self, username: TextString) -> bool { + info!("Allowing auth for user {:?}", username.as_str()); true } @@ -202,63 +181,16 @@ impl ServBehaviour for DemoServer { } async fn session(socket: &mut TcpSocket<'_>) -> sunset::Result<()> { - let mut app = DemoServer::new()?; - - let mut ssh_rxbuf = [0; 4000]; - let mut ssh_txbuf = [0; 4000]; - let serv = SSHServer::new(&mut ssh_rxbuf, &mut ssh_txbuf, &mut app)?; - let serv = &serv; - - let app = Mutex::<NoopRawMutex, _>::new(app); - - let (mut rsock, mut wsock) = socket.split(); - - let tx = async { - loop { - // TODO: make sunset read directly from socket, no intermediate buffer. - let mut buf = [0; 1024]; - trace!("tx read"); - let l = serv.read(&mut buf).await?; - trace!("tx read done"); - let mut buf = &buf[..l]; - while buf.len() > 0 { - let n = wsock.write(buf).await.expect("TODO handle write error"); - buf = &buf[n..]; - } - trace!("tx write done"); - } - #[allow(unreachable_code)] - Ok::<_, sunset::Error>(()) - }; - - let rx = async { - loop { - // TODO: make sunset read directly from socket, no intermediate buffer. - let mut buf = [0; 1024]; - trace!("rx read"); - let l = rsock.read(&mut buf).await.expect("TODO handle read error"); - trace!("rx read done {l}"); - let mut buf = &buf[..l]; - while buf.len() > 0 { - let n = serv.write(&buf).await?; - buf = &buf[n..]; - } - trace!("rx write done"); - } - #[allow(unreachable_code)] - Ok::<_, sunset::Error>(()) - }; - - let prog = async { - loop { - serv.progress(&app).await?; - } - #[allow(unreachable_code)] - Ok::<_, sunset::Error>(()) - }; - join3(rx, tx, prog).await; - - Ok(()) + let mut app = DemoServer::new()?; + + let mut ssh_rxbuf = [0; 2000]; + let mut ssh_txbuf = [0; 2000]; + let serv = SSHServer::new(&mut ssh_rxbuf, &mut ssh_txbuf, &mut app)?; + let serv = &serv; + + let app = Mutex::<NoopRawMutex, _>::new(app); + + serv.run(socket, &app).await } static EXECUTOR: StaticCell<Executor> = StaticCell::new(); diff --git a/embassy/src/embassy_sunset.rs b/embassy/src/embassy_sunset.rs index 2646ec2eca0b7ec5d7e99944bbe1201676cdbe71..31f4b120021685b7f7d3abc6fb815b0942e82f46 100644 --- a/embassy/src/embassy_sunset.rs +++ b/embassy/src/embassy_sunset.rs @@ -83,6 +83,7 @@ impl<'a> EmbassySunset<'a> { } // inner dropped } + warn!("progress unlocked"); // idle until input is received // TODO do we also want to wake in other situations? diff --git a/embassy/src/server.rs b/embassy/src/server.rs index 742cb493b69bd43cddac215593a29cd92acb6347..b5958cb4cb8ab9f02d5ab8dbee5735c7dd03a979 100644 --- a/embassy/src/server.rs +++ b/embassy/src/server.rs @@ -1,5 +1,7 @@ use embassy_sync::mutex::Mutex; use embassy_sync::blocking_mutex::raw::{NoopRawMutex, RawMutex}; +use embassy_futures::join::join3; +use embassy_net::tcp::TcpSocket; use sunset::*; @@ -28,6 +30,56 @@ impl<'a> SSHServer<'a> { self.sunset.progress_server(b).await } + pub async fn run<M>(&self, socket: &mut TcpSocket<'_>, b: &Mutex<M, impl ServBehaviour>) -> Result<()> + where M: RawMutex + { + let (mut rsock, mut wsock) = socket.split(); + + let tx = async { + loop { + // TODO: make sunset read directly from socket, no intermediate buffer. + let mut buf = [0; 1024]; + let l = self.read(&mut buf).await?; + let mut buf = &buf[..l]; + while buf.len() > 0 { + let n = wsock.write(buf).await.expect("TODO handle write error"); + buf = &buf[n..]; + } + } + #[allow(unreachable_code)] + Ok::<_, sunset::Error>(()) + }; + + let rx = async { + loop { + // TODO: make sunset read directly from socket, no intermediate buffer. + let mut buf = [0; 1024]; + let l = rsock.read(&mut buf).await.expect("TODO handle read error"); + let mut buf = &buf[..l]; + while buf.len() > 0 { + let n = self.write(&buf).await?; + buf = &buf[n..]; + } + } + #[allow(unreachable_code)] + Ok::<_, sunset::Error>(()) + }; + + let prog = async { + loop { + self.progress(b).await?; + } + #[allow(unreachable_code)] + Ok::<_, sunset::Error>(()) + }; + + + // TODO: handle results + join3(rx, tx, prog).await; + + Ok(()) + } + // pub async fn channel(&mut self, ch: u32) -> Result<(ChanInOut<'a>, Option<ChanExtOut<'a>>)> { // let ty = self.sunset.with_runner(|r| r.channel_type(ch)).await?; // let inout = ChanInOut::new(ch, &self.sunset);