refactor(upload): route upload commands to dedicated handler

This commit is contained in:
Stanislav N Mikhailov
2026-08-10 14:17:29 +03:00
parent 3c3487b554
commit e45b86cd20
4 changed files with 61 additions and 91 deletions
+42 -84
View File
@@ -8,17 +8,12 @@ use tokio::{
net::TcpStream, net::TcpStream,
}; };
use crate::protocol::{ use crate::{protocol::{
decode_header, Command, HEADER_SIZE, Header, MAX_BODY_SIZE, decode_header,
Header, }, upload};
HEADER_SIZE,
MAX_BODY_SIZE,
Command,
};
struct IncomingMessage { struct IncomingMessage {
header: Header, header: Header,
body: Vec<u8>,
} }
pub struct Connection { pub struct Connection {
@@ -51,7 +46,7 @@ impl Connection {
while let Some(message) = self.read_message().await? { while let Some(message) = self.read_message().await? {
self.message_count += 1; self.message_count += 1;
self.handle_message(message).await?; self.print_message(message).await?;
} }
println!( println!(
@@ -69,13 +64,45 @@ impl Connection {
let Some(header) = self.read_header().await? else { let Some(header) = self.read_header().await? else {
return Ok(None); 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:}")
)
}
);
}
let body = self.read_body(header.body_size()).await?; Command::Download => {
println!("Команда DOWNLOAD");
}
Ok(Some(IncomingMessage { Command::Delete => {
header, println!("Команда DELETE");
body, }
}))
Command::Stat => {
println!("Команда STAT");
}
Command::FileData => {
println!("Команда FILEDATA");
}
Command::Response => {
println!("Команда RESPONSE");
}
}
//let body = self.read_body(header.body_size()).await?;
Ok(None)
} }
async fn read_header(&mut self) -> io::Result<Option<Header>> { async fn read_header(&mut self) -> io::Result<Option<Header>> {
@@ -100,59 +127,10 @@ impl Connection {
format!("Ошибка разбора заголовка: {error:?}"), 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)) Ok(Some(header))
} }
async fn read_body( //todo: анахронизм, убрать после реализации storage async fn print_message(
&mut self,
body_size: u64,
) -> io::Result<Vec<u8>> {
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(
&mut self, &mut self,
message: IncomingMessage, message: IncomingMessage,
) -> io::Result<()> { ) -> io::Result<()> {
@@ -162,26 +140,6 @@ impl Connection {
self.message_count, self.message_count,
message.header 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(()) Ok(())
} }
} }
+7 -7
View File
@@ -29,21 +29,21 @@
### 2. Создать постоянный модуль загрузки ### 2. Создать постоянный модуль загрузки
- [ ] Создать `upload.rs`. - [✔] Создать `upload.rs`.
- [ ] Подключить его в `main.rs`: - [✔] Подключить его в `main.rs`:
```rust ```rust
mod upload; mod upload;
``` ```
- [ ] Создать в нём асинхронную функцию `handle()`. - [✔ Создать в нём асинхронную функцию `handle()`.
- [ ] Передать в неё: - [✔] Передать в неё:
- `&mut` сетевой поток; - `&mut` сетевой поток;
- проверенный `Header`. - проверенный `Header`.
- [ ] Пока только вывести заголовок и вернуть `Ok(())`. - [✔] Пока только вывести заголовок и вернуть `Ok(())`.
- [ ] Убедиться, что после вызова управление возвращается в цикл `Connection`. - [✔] Убедиться, что после вызова управление возвращается в цикл `Connection`.
Первая форма может иметь такой смысл: Первая форма может иметь такой смысл:
@@ -59,7 +59,7 @@ pub async fn handle(
### 3. Убрать чтение всего тела в `Vec` ### 3. Убрать чтение всего тела в `Vec`
- [ ] Не вызывать текущий `read_body()` для команды `UPLOAD`. - [✔] Не вызывать текущий `read_body()` для команды `UPLOAD`.
- [ ] Не создавать: - [ ] Не создавать:
```rust ```rust
+1
View File
@@ -1,5 +1,6 @@
mod connection; //модуль отвечающий за соединения mod connection; //модуль отвечающий за соединения
mod protocol; //модуль отвечающий за протокол ... mod protocol; //модуль отвечающий за протокол ...
mod upload; //Модуль отвечающий за загрузку файла
use tokio::net::{TcpListener}; use tokio::net::{TcpListener};
use tokio::io; use tokio::io;
+11
View File
@@ -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(())
}