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_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![allow(async_fn_in_trait)]
|
#![allow(async_fn_in_trait)]
|
||||||
|
#![feature(slice_split_once)]
|
||||||
|
|
||||||
|
use core::fmt::{Debug, Write};
|
||||||
use core::str::from_utf8;
|
use core::str::from_utf8;
|
||||||
use cyw43_pio::{PioSpi, DEFAULT_CLOCK_DIVIDER};
|
use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi};
|
||||||
use log::{info, warn};
|
use defmt::println;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_net::tcp::TcpSocket;
|
use embassy_net::tcp::TcpSocket;
|
||||||
use embassy_net::{Config, StackResources};
|
use embassy_net::{Config, StackResources};
|
||||||
use embassy_rp::bind_interrupts;
|
use embassy_rp::bind_interrupts;
|
||||||
use embassy_rp::clocks::RoscRng;
|
use embassy_rp::clocks::RoscRng;
|
||||||
use embassy_rp::gpio::{Level, Output};
|
use embassy_rp::gpio::{Level, Output};
|
||||||
|
use embassy_rp::peripherals::USB;
|
||||||
use embassy_rp::peripherals::{DMA_CH0, PIO0};
|
use embassy_rp::peripherals::{DMA_CH0, PIO0};
|
||||||
use embassy_rp::pio::{InterruptHandler as PioInterruptHandler, Pio};
|
use embassy_rp::pio::{InterruptHandler as PioInterruptHandler, Pio};
|
||||||
|
use embassy_rp::usb::{Driver, InterruptHandler as UsbInterruptHandler};
|
||||||
use embassy_time::Duration;
|
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 rand_core::RngCore;
|
||||||
use static_cell::StaticCell;
|
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 _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
@ -33,7 +37,9 @@ async fn logger_task(driver: Driver<'static, USB>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[embassy_executor::task]
|
#[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
|
runner.run().await
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +93,12 @@ async fn main(spawner: Spawner) {
|
|||||||
|
|
||||||
// Init network stack
|
// Init network stack
|
||||||
static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
|
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();
|
spawner.spawn(net_task(runner)).unwrap();
|
||||||
|
|
||||||
@ -97,10 +108,11 @@ async fn main(spawner: Spawner) {
|
|||||||
let mut rx_buffer = [0; 4096];
|
let mut rx_buffer = [0; 4096];
|
||||||
let mut tx_buffer = [0; 4096];
|
let mut tx_buffer = [0; 4096];
|
||||||
let mut buf = [0; 4096];
|
let mut buf = [0; 4096];
|
||||||
|
let mut res_buf = Vec::<u8, 4096>::new();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
|
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;
|
control.gpio_set(0, false).await;
|
||||||
info!("Listening on TCP:1234...");
|
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(()) => {}
|
Ok(()) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("write error: {:?}", 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