diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..5d56faf --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/src/main.rs b/src/main.rs index cdf78cb..41afbe4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,25 +1,29 @@ #![no_std] #![no_main] #![allow(async_fn_in_trait)] +#![feature(slice_split_once)] +use core::fmt::{Debug, Write}; use core::str::from_utf8; -use cyw43_pio::{PioSpi, DEFAULT_CLOCK_DIVIDER}; -use log::{info, warn}; +use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi}; +use defmt::println; use embassy_executor::Spawner; use embassy_net::tcp::TcpSocket; use embassy_net::{Config, StackResources}; use embassy_rp::bind_interrupts; use embassy_rp::clocks::RoscRng; use embassy_rp::gpio::{Level, Output}; +use embassy_rp::peripherals::USB; use embassy_rp::peripherals::{DMA_CH0, PIO0}; use embassy_rp::pio::{InterruptHandler as PioInterruptHandler, Pio}; +use embassy_rp::usb::{Driver, InterruptHandler as UsbInterruptHandler}; use embassy_time::Duration; -use embedded_io_async::Write; +use embassy_time::Timer; +use embedded_io_async::Write as _; +use heapless::{String, Vec}; +use log::{info, warn}; use rand_core::RngCore; use static_cell::StaticCell; -use embassy_rp::peripherals::USB; -use embassy_rp::usb::{Driver, InterruptHandler as UsbInterruptHandler}; -use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { @@ -33,7 +37,9 @@ async fn logger_task(driver: Driver<'static, USB>) { } #[embassy_executor::task] -async fn cyw43_task(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>) -> ! { +async fn cyw43_task( + runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>, +) -> ! { runner.run().await } @@ -87,7 +93,12 @@ async fn main(spawner: Spawner) { // Init network stack static RESOURCES: StaticCell> = StaticCell::new(); - let (stack, runner) = embassy_net::new(net_device, config, RESOURCES.init(StackResources::new()), seed); + let (stack, runner) = embassy_net::new( + net_device, + config, + RESOURCES.init(StackResources::new()), + seed, + ); spawner.spawn(net_task(runner)).unwrap(); @@ -97,10 +108,11 @@ async fn main(spawner: Spawner) { let mut rx_buffer = [0; 4096]; let mut tx_buffer = [0; 4096]; let mut buf = [0; 4096]; + let mut res_buf = Vec::::new(); loop { let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); - socket.set_timeout(Some(Duration::from_secs(10))); + socket.set_timeout(Some(Duration::from_secs(30))); control.gpio_set(0, false).await; info!("Listening on TCP:1234..."); @@ -125,9 +137,95 @@ async fn main(spawner: Spawner) { } }; - info!("rxd {}", from_utf8(&buf[..n]).unwrap()); + info!("request :\n{}", from_utf8(&buf[..n]).unwrap()); - match socket.write_all(&buf[..n]).await { + let mut headers: &[u8] = &buf[..n]; + let mut content: &[u8] = &[]; + for i in 0..(n - 1) { + if &buf[i..i + 1] == b"\r\n" { + headers = &buf[0..i]; + if i + 2 < n { + content = &buf[i + 2..n]; + } + } + } + + let mut headers = headers.split(|x| *x == b'\n'); + let (request_type, path) = match headers.next() { + None => { + warn!("Empty request"); + break; + } + Some(l1) => { + let mut l1 = l1.split(|x| *x == b' '); + ( + match l1.next() { + Some(b"GET") => HttpRequestType::Get, + Some(b"POST") => HttpRequestType::Post, + Some(t) => { + warn!("Unknown request type : {}", from_utf8(t).unwrap()); + break; + } + None => { + warn!("No request type"); + break; + } + }, + match l1.next() { + Some(path) => path, + None => { + warn!("No path"); + break; + } + }, + ) + } + }; + + let (code, res): (HttpResCode, &str) = match path { + b"/" => ( + HttpResCode::Ok, + "\r\n\ + \r\n\ + \r\n\ +

Titre

\r\n\ +

contenu

\r\n\ + \r\n\ + ", + ), + _ => (HttpResCode::NotFound, ""), + }; + + //b"HTTP/1.1 200 OK\r\n\ + // Content-Type: text/html\r\n\ + // Content-Length: 81\r\n\r\n\ + // \r\n\ + // \r\n\ + // \r\n\ + //

Titre

\r\n\ + //

contenu

\r\n\ + // \r\n\ + // " + + // Write response to buf + res_buf.clear(); + if let Err(e) = write!( + &mut res_buf, + "{}\r\n\ + Content-Type: text/html\r\n\ + Content-Length: {}\r\n\r\n\ + {}", + Into::<&str>::into(code), + res.len(), + res + ) { + warn!("write error: {:?}", e); + break; + } + + info!("response :\n{}", from_utf8(&res_buf).unwrap()); + + match socket.write_all(&res_buf).await { Ok(()) => {} Err(e) => { warn!("write error: {:?}", e); @@ -137,3 +235,22 @@ async fn main(spawner: Spawner) { } } } + +enum HttpRequestType { + Get, + Post, +} + +#[derive(Debug, Clone, Copy)] +enum HttpResCode { + Ok, + NotFound, +} +impl Into<&str> for HttpResCode { + fn into(self) -> &'static str { + match self { + HttpResCode::Ok => "HTTP/1.1 200 OK", + HttpResCode::NotFound => "HTTP/1.1 404 NOT FOUND", + } + } +}