file transfer: improve / fix
This commit is contained in:
@@ -3,7 +3,10 @@ use std::{convert::TryInto, path::Path};
|
||||
use bytes::Bytes;
|
||||
use lanspread_db::db::GameFileDescription;
|
||||
use lanspread_utils::maybe_addr;
|
||||
use s2n_quic::stream::SendStream;
|
||||
use s2n_quic::{
|
||||
connection,
|
||||
stream::{Error as StreamError, SendStream},
|
||||
};
|
||||
use tokio::{
|
||||
io::{AsyncReadExt, AsyncSeekExt},
|
||||
time::Instant,
|
||||
@@ -33,6 +36,8 @@ async fn stream_file_bytes(
|
||||
}
|
||||
|
||||
let mut remaining = length.unwrap_or(u64::MAX);
|
||||
let expect_exact = length.is_some();
|
||||
let mut transfer_complete = matches!(length, Some(0));
|
||||
let mut total_bytes = 0u64;
|
||||
let mut last_total_bytes = 0u64;
|
||||
let mut timestamp = Instant::now();
|
||||
@@ -47,6 +52,9 @@ async fn stream_file_bytes(
|
||||
|
||||
let bytes_read = file.read(&mut buf[..read_len]).await?;
|
||||
if bytes_read == 0 {
|
||||
if !expect_exact {
|
||||
transfer_complete = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -54,6 +62,11 @@ async fn stream_file_bytes(
|
||||
remaining = remaining.saturating_sub(bytes_read as u64);
|
||||
total_bytes += bytes_read as u64;
|
||||
|
||||
if expect_exact && remaining == 0 {
|
||||
transfer_complete = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if last_total_bytes + 10_000_000 < total_bytes {
|
||||
let elapsed = timestamp.elapsed();
|
||||
let diff_bytes = total_bytes - last_total_bytes;
|
||||
@@ -76,10 +89,26 @@ async fn stream_file_bytes(
|
||||
validated_path.display()
|
||||
);
|
||||
|
||||
tx.close().await?;
|
||||
match tx.close().await {
|
||||
Ok(()) => {}
|
||||
Err(err) if transfer_complete && is_clean_remote_close(&err) => {
|
||||
log::debug!("{remote_addr} closed stream after transfer completion: {err}");
|
||||
}
|
||||
Err(err) => return Err(err.into()),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_clean_remote_close(err: &StreamError) -> bool {
|
||||
matches!(
|
||||
err,
|
||||
StreamError::ConnectionError {
|
||||
error: connection::Error::Closed { .. },
|
||||
..
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn send_game_file_data(
|
||||
game_file_desc: &GameFileDescription,
|
||||
tx: &mut SendStream,
|
||||
|
||||
Reference in New Issue
Block a user