Working http server
This commit is contained in:
parent
bb7f643134
commit
ef8d06b516
2
rust-toolchain.toml
Normal file
2
rust-toolchain.toml
Normal file
@ -0,0 +1,2 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
139
src/main.rs
139
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<StackResources<3>> = 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::<u8, 4096>::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,
|
||||
"<!DOCTYPE html>\r\n\
|
||||
<html>\r\n\
|
||||
<body>\r\n\
|
||||
<h1>Titre</h1>\r\n\
|
||||
<p>contenu</p>\r\n\
|
||||
</body>\r\n\
|
||||
</html>",
|
||||
),
|
||||
_ => (HttpResCode::NotFound, ""),
|
||||
};
|
||||
|
||||
//b"HTTP/1.1 200 OK\r\n\
|
||||
// Content-Type: text/html\r\n\
|
||||
// Content-Length: 81\r\n\r\n\
|
||||
// <!DOCTYPE html>\r\n\
|
||||
// <html>\r\n\
|
||||
// <body>\r\n\
|
||||
// <h1>Titre</h1>\r\n\
|
||||
// <p>contenu</p>\r\n\
|
||||
// </body>\r\n\
|
||||
// </html>"
|
||||
|
||||
// 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",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user