From 94030c34cac96b6a888339c43c94f1479c002db6 Mon Sep 17 00:00:00 2001 From: Stanislav N Mikhailov Date: Fri, 7 Aug 2026 03:41:19 +0300 Subject: [PATCH] refactor(protocol): centralize header parsing and validation --- src/connection.rs | 21 ++++++++------------- src/protocol.rs | 33 +++++++++++++++++++++++++++------ 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/connection.rs b/src/connection.rs index e9b5d31..d90b33e 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -9,7 +9,7 @@ use tokio::{ }; use crate::protocol::{ - parse_header, + decode_header, Header, HEADER_SIZE, MAX_BODY_SIZE, @@ -87,24 +87,19 @@ impl Connection { if bytes_read == 0 { return Ok(None); } + + // Читаем остальную часть буфера от 1 до конца + self.stream.read_exact(&mut buffer[1..]).await?; - 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)) } diff --git a/src/protocol.rs b/src/protocol.rs index f1ab0d8..51ed7b8 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -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 { + // Парсим заголовок: + 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(())