From b90c978a38f99ea6b0967441c650b25f2f13f978 Mon Sep 17 00:00:00 2001 From: Arkitu <85173315+Arkitu@users.noreply.github.com> Date: Thu, 1 May 2025 21:30:55 +0200 Subject: [PATCH] save --- Cargo.lock | 7 ++ Cargo.toml | 3 +- src/apps/chat.html | 53 +++++++++++++++ src/apps/chat.rs | 163 +++++++++++++++++++++++++++++++++++++++++++++ src/apps/mod.rs | 1 + src/main.rs | 15 +---- src/socket.rs | 21 ++++-- 7 files changed, 243 insertions(+), 20 deletions(-) create mode 100644 src/apps/chat.html create mode 100644 src/apps/chat.rs diff --git a/Cargo.lock b/Cargo.lock index 8471634..6c0442c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1111,6 +1111,7 @@ dependencies = [ "panic-probe", "portable-atomic", "rand_core", + "ringbuffer", "serde", "serde-json-core", "static_cell", @@ -1304,6 +1305,12 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "ringbuffer" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3df6368f71f205ff9c33c076d170dd56ebf68e8161c733c0caa07a7a5509ed53" + [[package]] name = "rp-pac" version = "7.0.0" diff --git a/Cargo.toml b/Cargo.toml index e190936..f430dbf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,4 +56,5 @@ serde = { version = "*", optional = true, default-features = false, features = [ "derive", ] } dhcparse = { version = "*", default-features = false, optional = true } -dnsparse = { version = "*", optional = true } \ No newline at end of file +dnsparse = { version = "*", optional = true } +ringbuffer = { version = "*", default-features = false } \ No newline at end of file diff --git a/src/apps/chat.html b/src/apps/chat.html new file mode 100644 index 0000000..706ec69 --- /dev/null +++ b/src/apps/chat.html @@ -0,0 +1,53 @@ + + + + + + + +

Chat

+ + +
+ Enter your name : + + +
+ + diff --git a/src/apps/chat.rs b/src/apps/chat.rs new file mode 100644 index 0000000..38665a8 --- /dev/null +++ b/src/apps/chat.rs @@ -0,0 +1,163 @@ +use core::fmt::Write; +use heapless::{String, Vec}; +use log::info; +use pico_website::unwrap; +use ringbuffer::{ConstGenericRingBuffer, RingBuffer}; + +use crate::socket::HttpResCode; + +use super::App; + +const MEMORY_SIZE: usize = 16; + +pub struct ChatApp { + res_buf: Vec, + msgs: ConstGenericRingBuffer, + next_msg: u16, +} +impl ChatApp { + pub fn new() -> Self { + let mut msgs = ConstGenericRingBuffer::new(); + + let mut aut0 = String::new(); + write!(&mut aut0, "rael").unwrap(); + let mut msg0 = String::new(); + write!(&mut msg0, "Prout...").unwrap(); + msgs.push(Message { + author: aut0, + content: msg0, + }); + let mut aut1 = String::new(); + write!(&mut aut1, "josh").unwrap(); + let mut msg1 = String::new(); + write!(&mut msg1, "Salut !\nJe m'appelle...").unwrap(); + msgs.push(Message { + author: aut1, + content: msg1, + }); + + Self { + res_buf: Vec::new(), + msgs, + next_msg: 2, + } + } +} +impl App for ChatApp { + fn socket_name(&self) -> &'static str { + "chat" + } + async fn handle_request<'a>(&'a mut self, path: &str) -> (HttpResCode, &'static str, &'a [u8]) { + match path { + "/" | "/index" | "/index.html" | "/chat" | "/chat.html" => { + (HttpResCode::Ok, "html", include_bytes!("./chat.html")) + } + path => { + let (path, args) = path.split_once('?').unwrap_or((path, "")); + let mut load = None; + let mut username = None; + for arg in args.split('&') { + match arg.split_once('=') { + Some(("load", n)) => { + let n: u16 = match n.parse() { + Ok(v) => v, + Err(_) => return (HttpResCode::BadRequest, "", &[]), + }; + if n > 0 { + load = Some(n); + } + } + Some(("username", u)) => { + if u.len() < 3 || u.len() > 16 { + return (HttpResCode::BadRequest, "", &[]); + } + username = Some(u); + } + _ => {} + } + } + if path == "/chat" && username.is_some() { + return ( + HttpResCode::Ok, + "html", + "
", + ); + } else if path.starts_with("/chat/message/abs/") && path.len() > 18 { + let msg_id: u16 = match path[18..].parse() { + Ok(n) => n, + Err(_) => return (HttpResCode::BadRequest, "", &[]), + }; + info!("msg_id = {:?}", msg_id); + if msg_id >= self.next_msg { + return (HttpResCode::BadRequest, "", &[]); + } + if msg_id < self.next_msg.saturating_sub(MEMORY_SIZE as u16 + 1) { + return (HttpResCode::NoContent, "", &[]); + } + let msg = match self + .msgs + .get_signed((msg_id as isize) + 1 - (self.next_msg as isize)) + { + Some(msg) => msg, + None => return (HttpResCode::NoContent, "", &[]), + }; + self.res_buf.clear(); + unwrap(write!(&mut self.res_buf, "
{}: {}
", + msg.author, msg.content + )) + .await; + // unwrap(write!( + // &mut self.res_buf, + // "
\ + // {}: {}\ + //
", + // match load { + // Some(target) => "hx-get=\"/chat/message{}\" \ + // hx-target=\"next .message\" \ + // hx-swap=\"outerHTML\" \ + // hx-trigger=\"load\"\" + // } + // (msg_num + 1), + // msg.author, + // msg.content + // )) + // .await; + return (HttpResCode::Ok, "html", &self.res_buf); + } else { + (HttpResCode::NotFound, "", &[]) + } + } + } + } +} + +struct Message { + author: String<16>, + content: String<256>, +} diff --git a/src/apps/mod.rs b/src/apps/mod.rs index 9699932..4074c14 100644 --- a/src/apps/mod.rs +++ b/src/apps/mod.rs @@ -1,5 +1,6 @@ use crate::socket::HttpResCode; +pub mod chat; pub mod index; pub mod ttt; diff --git a/src/main.rs b/src/main.rs index 8774e8c..0c9e260 100644 --- a/src/main.rs +++ b/src/main.rs @@ -170,18 +170,9 @@ async fn main(spawner: Spawner) { unwrap(spawner.spawn(dns::dns_server(stack))).await; unwrap(spawner.spawn(socket::index_listen_task(stack, 80))).await; - unwrap(spawner.spawn(socket::ttt_listen_task( - stack, - apps::ttt::TttApp::new(apps::ttt::Team::Zero), - 8080, - ))) - .await; - unwrap(spawner.spawn(socket::ttt_listen_task( - stack, - apps::ttt::TttApp::new(apps::ttt::Team::One), - 8081, - ))) - .await; + unwrap(spawner.spawn(socket::ttt_listen_task(stack, apps::ttt::Team::Zero, 8080))).await; + unwrap(spawner.spawn(socket::ttt_listen_task(stack, apps::ttt::Team::One, 8081))).await; + unwrap(spawner.spawn(socket::chat_listen_task(stack, 8082))).await; } #[cfg(feature = "wifi-connect")] diff --git a/src/socket.rs b/src/socket.rs index 9355839..6b2842b 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -6,11 +6,11 @@ use embedded_io_async::Write as _; use heapless::Vec; use log::{info, warn}; -use crate::apps::{App, index::IndexApp, ttt}; +use crate::apps::{App, chat, index::IndexApp, ttt}; #[embassy_executor::task(pool_size = 2)] -pub async fn ttt_listen_task(stack: embassy_net::Stack<'static>, app: ttt::TttApp, port: u16) { - listen_task(stack, app, port).await +pub async fn ttt_listen_task(stack: embassy_net::Stack<'static>, team: ttt::Team, port: u16) { + listen_task(stack, ttt::TttApp::new(team), port).await } #[embassy_executor::task(pool_size = 2)] @@ -18,15 +18,20 @@ pub async fn index_listen_task(stack: embassy_net::Stack<'static>, port: u16) { listen_task(stack, IndexApp, port).await } +#[embassy_executor::task(pool_size = 1)] +pub async fn chat_listen_task(stack: embassy_net::Stack<'static>, port: u16) { + listen_task(stack, chat::ChatApp::new(), port).await +} + pub async fn listen_task(stack: embassy_net::Stack<'static>, mut app: impl App, port: u16) { // loop { // info!("team:{:?}", team); // Timer::after_millis(0).await; // } - let mut rx_buffer = [0; 4096]; - let mut tx_buffer = [0; 4096]; - let mut buf = [0; 4096]; - let mut res_head_buf = Vec::::new(); + let mut rx_buffer = [0; 8192]; + let mut tx_buffer = [0; 8192]; + let mut buf = [0; 1024]; + let mut res_head_buf = Vec::::new(); loop { Timer::after_secs(0).await; @@ -191,6 +196,7 @@ impl Into<&str> for HttpRequestType { pub enum HttpResCode { Ok, NoContent, + BadRequest, NotFound, Forbidden, } @@ -199,6 +205,7 @@ impl Into<&str> for HttpResCode { match self { HttpResCode::Ok => "HTTP/1.1 200 OK", HttpResCode::NoContent => "HTTP/1.1 204 NO CONTENT", + HttpResCode::BadRequest => "HTTP/1.1 400 BAD REQUEST", HttpResCode::NotFound => "HTTP/1.1 404 NOT FOUND", HttpResCode::Forbidden => "HTTP/1.1 403 FORBIDDEN", }