sark-core 0.11.0

the L7 layer for dope
Documentation
use std::ops::Range;

#[derive(Clone, Copy, Debug)]
pub struct ParsedRequestHead<'a> {
    pub method: &'a [u8],
    pub target: &'a [u8],
    pub version: &'a [u8],
    pub headers_start: usize,
}

impl ParsedRequestHead<'_> {
    pub fn parse(buf: &[u8]) -> Option<ParsedRequestHead<'_>> {
        let start_line_end = memchr::memchr(b'\r', buf)?;
        if start_line_end + 1 >= buf.len() || buf[start_line_end + 1] != b'\n' {
            return None;
        }
        let line = &buf[..start_line_end];
        if line.len() < 9 {
            return None;
        }
        let version_start = line.len() - 8;
        if version_start == 0 || line[version_start - 1] != b' ' {
            return None;
        }
        let method_end = line.iter().position(|&byte| byte == b' ')?;
        if method_end == 0 || method_end >= version_start - 1 {
            return None;
        }
        let method = &line[..method_end];
        let target = &line[method_end + 1..version_start - 1];
        let version = &line[version_start..];
        if target.is_empty()
            || (version != b"HTTP/1.1" && version != b"HTTP/1.0")
            || !crate::http::scan::request_target_is_valid(target)
        {
            return None;
        }
        Some(ParsedRequestHead {
            method,
            target,
            version,
            headers_start: start_line_end + 2,
        })
    }

    pub fn head_end(bytes: &[u8]) -> Option<Range<usize>> {
        memchr::memmem::find(bytes, b"\r\n\r\n").map(|s| s..s + 4)
    }
}