From e45b86cd20424b957767f4e30e14a2f860320b54 Mon Sep 17 00:00:00 2001 From: Stanislav N Mikhailov Date: Mon, 10 Aug 2026 14:17:29 +0300 Subject: [PATCH] refactor(upload): route upload commands to dedicated handler --- src/connection.rs | 126 ++++++++++++++++------------------------------ src/main.MD | 14 +++--- src/main.rs | 1 + src/upload.rs | 11 ++++ 4 files changed, 61 insertions(+), 91 deletions(-) create mode 100644 src/upload.rs diff --git a/src/connection.rs b/src/connection.rs index 50dbc58..ea1f98d 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -8,17 +8,12 @@ use tokio::{ net::TcpStream, }; -use crate::protocol::{ - decode_header, - Header, - HEADER_SIZE, - MAX_BODY_SIZE, - Command, -}; +use crate::{protocol::{ + Command, HEADER_SIZE, Header, MAX_BODY_SIZE, decode_header, +}, upload}; struct IncomingMessage { header: Header, - body: Vec, } pub struct Connection { @@ -51,7 +46,7 @@ impl Connection { while let Some(message) = self.read_message().await? { self.message_count += 1; - self.handle_message(message).await?; + self.print_message(message).await?; } println!( @@ -69,13 +64,45 @@ impl Connection { let Some(header) = self.read_header().await? else { return Ok(None); }; + //Заголовок скачен и валиден. Получаем команду из заголовка + match header.command() { + Command::Upload => { + println!("Команда UPLOAD"); + let upl_result= + upload::handle(&mut self.stream, header).await.map_err(|error| { + io::Error::new( + io::ErrorKind::InvalidData, + format!("Ошибка UPLOAD:{error:}") + ) + } + ); + } + + Command::Download => { + println!("Команда DOWNLOAD"); + } + + Command::Delete => { + println!("Команда DELETE"); + } + + Command::Stat => { + println!("Команда STAT"); + } + + Command::FileData => { + println!("Команда FILEDATA"); + } + + Command::Response => { + println!("Команда RESPONSE"); + } + } + - let body = self.read_body(header.body_size()).await?; + //let body = self.read_body(header.body_size()).await?; - Ok(Some(IncomingMessage { - header, - body, - })) + Ok(None) } async fn read_header(&mut self) -> io::Result> { @@ -100,59 +127,10 @@ impl Connection { format!("Ошибка разбора заголовка: {error:?}"), ) })?; - - //Заголовок скачен и валиден. Получаем команду из заголовка - match header.command() { - Command::Upload => { - println!("Команда UPLOAD"); - } - - Command::Download => { - println!("Команда DOWNLOAD"); - } - - Command::Delete => { - println!("Команда DELETE"); - } - - Command::Stat => { - println!("Команда STAT"); - } - - Command::FileData => { - println!("Команда FILEDATA"); - } - - Command::Response => { - println!("Команда RESPONSE"); - } - } - Ok(Some(header)) } - async fn read_body( //todo: анахронизм, убрать после реализации storage - &mut self, - body_size: u64, - ) -> io::Result> { - if body_size > MAX_BODY_SIZE { - return Err(io::Error::new( - io::ErrorKind::InvalidData, - format!( - "Размер тела {body_size} превышает лимит \ - {MAX_BODY_SIZE}" - ), - )); - } - - let mut body = vec![0_u8; body_size as usize]; - - self.stream.read_exact(&mut body).await?; - - Ok(body) - } - - async fn handle_message( + async fn print_message( &mut self, message: IncomingMessage, ) -> io::Result<()> { @@ -162,26 +140,6 @@ impl Connection { self.message_count, message.header ); - - // Это знание конкретной команды. - // Позже этот код можно вынести в отдельный handler.rs. - let body_text = String::from_utf8_lossy(&message.body); - - println!( - "Соединение {}: тело: {:?}", - self.id, - body_text - ); - - let response = format!( - "Соединение {}: запрос {} принят, cmd={:?}\n", - self.id, - message.header.request_id(), - message.header.command(), - ); - - self.stream.write_all(response.as_bytes()).await?; - Ok(()) } } \ No newline at end of file diff --git a/src/main.MD b/src/main.MD index 55b1a6a..2387009 100644 --- a/src/main.MD +++ b/src/main.MD @@ -29,21 +29,21 @@ ### 2. Создать постоянный модуль загрузки -- [ ] Создать `upload.rs`. -- [ ] Подключить его в `main.rs`: +- [✔] Создать `upload.rs`. +- [✔] Подключить его в `main.rs`: ```rust mod upload; ``` -- [ ] Создать в нём асинхронную функцию `handle()`. -- [ ] Передать в неё: +- [✔ Создать в нём асинхронную функцию `handle()`. +- [✔] Передать в неё: - `&mut` сетевой поток; - проверенный `Header`. -- [ ] Пока только вывести заголовок и вернуть `Ok(())`. -- [ ] Убедиться, что после вызова управление возвращается в цикл `Connection`. +- [✔] Пока только вывести заголовок и вернуть `Ok(())`. +- [✔] Убедиться, что после вызова управление возвращается в цикл `Connection`. Первая форма может иметь такой смысл: @@ -59,7 +59,7 @@ pub async fn handle( ### 3. Убрать чтение всего тела в `Vec` -- [ ] Не вызывать текущий `read_body()` для команды `UPLOAD`. +- [✔] Не вызывать текущий `read_body()` для команды `UPLOAD`. - [ ] Не создавать: ```rust diff --git a/src/main.rs b/src/main.rs index 4ad921c..aac1f64 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ mod connection; //модуль отвечающий за соединения mod protocol; //модуль отвечающий за протокол ... +mod upload; //Модуль отвечающий за загрузку файла use tokio::net::{TcpListener}; use tokio::io; diff --git a/src/upload.rs b/src/upload.rs new file mode 100644 index 0000000..62eb13d --- /dev/null +++ b/src/upload.rs @@ -0,0 +1,11 @@ +use tokio::{io, net::TcpStream, stream}; + +use crate::protocol::Header; + +pub async fn handle( + stream: &mut TcpStream, + header: Header, +) -> io::Result<()> { + println!("Обработчик UPLOAD получил заголовок: {header:?}"); + Ok(()) +} \ No newline at end of file