1use crate::{
2 error::Error,
3 handler::HttpHandler,
4 header::HttpHeader,
5 request::HttpRequest,
6 response::{HttpResponse, ResponseBody},
7 status_code::StatusCode,
8};
9use embassy_net::{Stack, tcp::TcpSocket};
10use embassy_net_08 as embassy_net;
11use embassy_time_05 as embassy_time;
12use embedded_io_async_07 as embedded_io_async;
13
14use embassy_time::{Duration, Timer, with_timeout};
15use embedded_io_async::Write as EmbeddedWrite;
16use heapless::Vec;
17
18const SERVER_BUFFER_SIZE: usize = 4096;
19const MAX_REQUEST_SIZE: usize = 4096;
20const DEFAULT_MAX_RESPONSE_SIZE: usize = 4096;
21
22#[derive(Debug, Clone, Copy)]
24pub struct ServerTimeouts {
25 pub accept_timeout: u64,
27 pub read_timeout: u64,
29 pub handler_timeout: u64,
31}
32
33impl Default for ServerTimeouts {
34 fn default() -> Self {
35 Self {
36 accept_timeout: 10,
37 read_timeout: 30,
38 handler_timeout: 60,
39 }
40 }
41}
42
43impl ServerTimeouts {
44 #[must_use]
46 pub fn new(accept_timeout: u64, read_timeout: u64, handler_timeout: u64) -> Self {
47 Self {
48 accept_timeout,
49 read_timeout,
50 handler_timeout,
51 }
52 }
53}
54
55pub struct HttpServer<
61 const RX_SIZE: usize,
62 const TX_SIZE: usize,
63 const REQ_SIZE: usize,
64 const MAX_RESPONSE_SIZE: usize,
65> {
66 port: u16,
67 timeouts: ServerTimeouts,
68}
69
70impl<
71 const RX_SIZE: usize,
72 const TX_SIZE: usize,
73 const REQ_SIZE: usize,
74 const MAX_RESPONSE_SIZE: usize,
75> HttpServer<RX_SIZE, TX_SIZE, REQ_SIZE, MAX_RESPONSE_SIZE>
76{
77 #[must_use]
79 pub fn new(port: u16) -> Self {
80 Self {
81 port,
82 timeouts: ServerTimeouts::default(),
83 }
84 }
85
86 #[must_use]
88 pub fn with_timeouts(port: u16, timeouts: ServerTimeouts) -> Self {
89 Self { port, timeouts }
90 }
91
92 pub async fn serve<H>(&mut self, stack: Stack<'_>, mut handler: H) -> !
97 where
98 H: HttpHandler,
99 {
100 defmt::info!("HTTP server started on port {}", self.port);
101
102 let mut rx_buffer = [0; RX_SIZE];
103 let mut tx_buffer = [0; TX_SIZE];
104 let mut buf = [0; REQ_SIZE];
105
106 loop {
107 let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
108 socket.set_timeout(Some(Duration::from_secs(self.timeouts.accept_timeout)));
109
110 if let Err(e) = socket.accept(self.port).await {
111 defmt::warn!("Accept error: {:?}", e);
112 Timer::after(Duration::from_millis(100)).await;
113 continue;
114 }
115
116 let n = match with_timeout(
117 Duration::from_secs(self.timeouts.read_timeout),
118 socket.read(&mut buf),
119 )
120 .await
121 {
122 Ok(Ok(0)) => {
123 continue;
125 }
126 Ok(Ok(n)) => n,
127 Ok(Err(e)) => {
128 defmt::warn!("Read error: {:?}", e);
129 continue;
130 }
131 Err(_) => {
132 defmt::warn!("Socket read timeout");
133 continue;
134 }
135 };
136
137 match self.handle_connection(&buf[..n], &mut handler).await {
139 Ok(response_bytes) => {
140 if let Err(e) = socket.write_all(&response_bytes).await {
141 defmt::warn!("Failed to write response: {:?}", e);
142 }
143 }
144 Err(e) => {
145 defmt::error!("Error handling request: {:?}", e);
146 let error_response = b"HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/plain\r\nContent-Length: 21\r\n\r\nInternal Server Error";
148 let _ = socket.write_all(error_response).await;
149 }
150 }
151
152 socket.close();
153 }
154 }
155
156 async fn handle_connection<H>(
157 &mut self,
158 buffer: &[u8],
159 handler: &mut H,
160 ) -> Result<Vec<u8, MAX_RESPONSE_SIZE>, Error>
161 where
162 H: HttpHandler,
163 {
164 let request = HttpRequest::try_from(buffer)?;
166
167 let response = match with_timeout(
169 Duration::from_secs(self.timeouts.handler_timeout),
170 handler.handle_request(&request),
171 )
172 .await
173 {
174 Ok(Ok(response)) => response,
175 Ok(Err(e)) => {
176 defmt::warn!("Handler error: {:?}", e);
177 let mut headers = Vec::new();
178 let _ = headers.push(HttpHeader::new("Content-Type", "text/plain"));
179 let error_response = HttpResponse {
180 status_code: StatusCode::InternalServerError,
181 headers,
182 body: ResponseBody::Text("Internal Server Error"),
183 };
184 return Ok(error_response.build_bytes::<MAX_RESPONSE_SIZE>());
185 }
186 Err(_) => {
187 defmt::warn!("Request handling timed out");
188 let mut headers = Vec::new();
189 let _ = headers.push(HttpHeader::new("Content-Type", "text/plain"));
190 let timeout_response = HttpResponse {
191 status_code: StatusCode::BadRequest,
192 headers,
193 body: ResponseBody::Text("Request Timeout"),
194 };
195 return Ok(timeout_response.build_bytes::<MAX_RESPONSE_SIZE>());
196 }
197 };
198
199 Ok(response.build_bytes::<MAX_RESPONSE_SIZE>())
200 }
201}
202
203pub type DefaultHttpServer =
205 HttpServer<SERVER_BUFFER_SIZE, SERVER_BUFFER_SIZE, MAX_REQUEST_SIZE, DEFAULT_MAX_RESPONSE_SIZE>;
206
207pub type SmallHttpServer = HttpServer<1024, 1024, 1024, 1024>;
209
210#[cfg(test)]
211mod tests {
212 use super::*;
213
214 #[test]
215 fn test_http_server_creation() {
216 let server: DefaultHttpServer = HttpServer::new(8080);
217 assert_eq!(server.port, 8080);
218 assert_eq!(server.timeouts.accept_timeout, 10);
219 assert_eq!(server.timeouts.read_timeout, 30);
220 assert_eq!(server.timeouts.handler_timeout, 60);
221
222 let server: SmallHttpServer = HttpServer::new(3000);
223 assert_eq!(server.port, 3000);
224 }
225
226 #[test]
227 fn test_server_timeouts() {
228 let timeouts = ServerTimeouts::default();
230 assert_eq!(timeouts.accept_timeout, 10);
231 assert_eq!(timeouts.read_timeout, 30);
232 assert_eq!(timeouts.handler_timeout, 60);
233
234 let custom_timeouts = ServerTimeouts::new(5, 15, 45);
236 assert_eq!(custom_timeouts.accept_timeout, 5);
237 assert_eq!(custom_timeouts.read_timeout, 15);
238 assert_eq!(custom_timeouts.handler_timeout, 45);
239
240 let server = HttpServer::<1024, 1024, 1024, 1024>::with_timeouts(8080, custom_timeouts);
242 assert_eq!(server.port, 8080);
243 assert_eq!(server.timeouts.accept_timeout, 5);
244 assert_eq!(server.timeouts.read_timeout, 15);
245 assert_eq!(server.timeouts.handler_timeout, 45);
246 }
247}