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