use hirun::net::AioFd; use hierr::{Error, Result}; static BODY: [u8; 4 << 20] = [0; 4 << 20]; pub struct HttpReq { status: u32, } impl HttpReq { pub const fn new() -> HttpReq { HttpReq { status: 0 } } fn parse(&mut self, data: &[u8]) { for c in data { match c { b'\r' => { if (self.status & 0x01) == 0 { self.status += 1; } else { self.status = 1; } } b'\n' => { if (self.status & 0x01) == 1 { self.status += 1; } else { self.status = 0; } } _ => self.status = 0, } if self.status == 4 { break; } } } fn is_ok(&self) -> bool { self.status == 4 } fn try_read(&mut self, conn: &mut AioFd<'_>) -> Result<()> { let mut buf = [0_u8; 1048]; match conn.try_recv(&mut buf, 0) { Ok(0) => Err(Error::new(libc::EINVAL)), Ok(n) => { self.parse(&buf[..n]); Ok(()) }, Err(e) => Err(e), } } pub async fn read(&mut self, conn: &mut AioFd<'_>) -> Result<()> { while !self.is_ok() { match self.try_read(conn) { Ok(_) => {}, Err(e) if e.errno == libc::EAGAIN => conn.wait_readable().await?, Err(e) => return Err(e), } } Ok(()) } } pub struct HttpRsp { body_size: usize, } impl HttpRsp { pub const fn new(body_size: usize) -> Self { Self { body_size } } async fn write_head(&self, conn: &mut AioFd<'_>) -> Result<()> { let hdr = format!( "HTTP/1.1 200 Ok\r\nContent-Length: {}\r\n\r\n", self.body_size ); let _ = conn.send_all(hdr.as_bytes(), 0).await?; Ok(()) } pub async fn write(&self, conn: &mut AioFd<'_>) -> Result<()> { self.write_head(conn).await?; let mut size = self.body_size; while size > 0 { let len = core::cmp::min(size, BODY.len()); let _ = conn.send_all(&BODY[..len], 0).await?; size -= len; } Ok(()) } }