refactor(protocol): centralize header parsing and validation

This commit is contained in:
Stanislav N Mikhailov
2026-08-07 03:41:19 +03:00
parent b80b8e9e04
commit 94030c34ca
2 changed files with 35 additions and 19 deletions
+5 -10
View File
@@ -9,7 +9,7 @@ use tokio::{
};
use crate::protocol::{
parse_header,
decode_header,
Header,
HEADER_SIZE,
MAX_BODY_SIZE,
@@ -88,23 +88,18 @@ impl Connection {
return Ok(None);
}
// Читаем остальную часть буфера от 1 до конца
self.stream.read_exact(&mut buffer[1..]).await?;
let (remaining, header) =
parse_header(&buffer).map_err(|error| {
//Парсим скачанный заголовок через nocloud_core::protocol parse_header
let header =
decode_header(&buffer).map_err(|error| {
io::Error::new(
io::ErrorKind::InvalidData,
format!("Ошибка разбора заголовка: {error:?}"),
)
})?;
// Мы дали парсеру ровно HEADER_SIZE байт.
debug_assert!(remaining.is_empty());
header.validate().map_err(|error| {
io::Error::new(io::ErrorKind::InvalidData, error)
})?;
Ok(Some(header))
}
+27 -6
View File
@@ -18,7 +18,10 @@ use nom::{
use thiserror::Error;
#[derive(Debug, Error)]
pub enum HeaderValidationError {
pub enum HeaderError {
#[error("Некорректный формат заголовка")]
InvalidFormat,
#[error("Неподдерживаемая версия протокола: {0}")]
UnsupportedVersion(u8),
@@ -38,7 +41,25 @@ pub struct Header {
body_size: u64,
}
pub fn parse_header(
pub fn decode_header(
input: &[u8; HEADER_SIZE],
) -> Result<Header, HeaderError> {
// Парсим заголовок:
let (remaining, header) = parse_header(input)
.map_err(|_| HeaderError::InvalidFormat)?;
// Выходим с ошибкой, если заголовок был недочитан парсером:
if !remaining.is_empty() {
return Err(HeaderError::InvalidFormat);
}
//Валидация заголовка
header.validate()?;
Ok(header)
}
fn parse_header(
input: &[u8],
) -> IResult<&[u8],Header> {
//1. Парсим магические байты "NCLD"
@@ -95,24 +116,24 @@ impl Header {
///Валидаторы для данных из заголовка:
///
// Валидация Header
pub fn validate(&self) -> Result<(), HeaderValidationError> {
pub fn validate(&self) -> Result<(), HeaderError> {
//Валидация version
if self.version != 1 {
return Err(
HeaderValidationError::UnsupportedVersion(self.version)
HeaderError::UnsupportedVersion(self.version)
);
}
// Валидация command
if self.command != 1 {
return Err(
HeaderValidationError::UnsupportedCommand(self.command)
HeaderError::UnsupportedCommand(self.command)
);
}
// Валидация flags
if !(0..=7).contains(&self.flags){
return Err(HeaderValidationError::UnsupportedFlagSet (self.flags));
return Err(HeaderError::UnsupportedFlagSet (self.flags));
};
Ok(())