refactor(protocol): centralize header parsing and validation
This commit is contained in:
+5
-10
@@ -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
@@ -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(())
|
||||
|
||||
Reference in New Issue
Block a user