Overall improvements

This commit is contained in:
Altuğ Bakan 2023-05-12 07:59:53 +00:00
parent 6df9155c32
commit 9096e94f00
5 changed files with 85 additions and 85 deletions

View file

@ -32,10 +32,7 @@ pub struct Config {
impl Config {
/// Creates a new configuration by parsing the supplied arguments. It is
/// intended for use with [`env::args()`].
pub fn new<T>(mut args: T) -> Result<Config, Box<dyn Error>>
where
T: Iterator<Item = String>,
{
pub fn new<T: Iterator<Item = String>>(mut args: T) -> Result<Config, Box<dyn Error>> {
let mut config = Config {
ip_address: Ipv4Addr::new(127, 0, 0, 1),
port: 69,

View file

@ -121,15 +121,22 @@ impl Server {
ErrorCode::FileExists => {
let worker_options =
parse_options(options, RequestType::Read(file_path.metadata()?.len()))?;
let mut socket: Box<dyn Socket>;
if self.single_port {
let mut socket = create_single_socket(&self.socket, to)?;
let single_socket = create_single_socket(&self.socket, to)?;
self.clients.insert(*to, single_socket.sender());
self.largest_block_size =
max(self.largest_block_size, worker_options.block_size);
socket = Box::new(single_socket);
} else {
socket = Box::new(create_multi_socket(&self.socket.local_addr()?, to)?);
}
socket.set_read_timeout(worker_options.timeout)?;
socket.set_write_timeout(worker_options.timeout)?;
self.clients.insert(*to, socket.sender());
self.largest_block_size =
max(self.largest_block_size, worker_options.block_size);
accept_request(
&socket,
options,
@ -144,26 +151,6 @@ impl Server {
worker_options.window_size,
);
worker.send()
} else {
let socket = create_multi_socket(&self.socket.local_addr()?, to)?;
socket.set_read_timeout(Some(worker_options.timeout))?;
socket.set_write_timeout(Some(worker_options.timeout))?;
accept_request(
&socket,
options,
RequestType::Read(file_path.metadata()?.len()),
)?;
let worker = Worker::new(
socket,
file_path.clone(),
worker_options.block_size,
worker_options.timeout,
worker_options.window_size,
);
worker.send()
}
}
_ => Err("Unexpected error code when checking file".into()),
}
@ -191,15 +178,22 @@ impl Server {
),
ErrorCode::FileNotFound => {
let worker_options = parse_options(options, RequestType::Write)?;
let mut socket: Box<dyn Socket>;
if self.single_port {
let mut socket = create_single_socket(&self.socket, to)?;
let single_socket = create_single_socket(&self.socket, to)?;
self.clients.insert(*to, single_socket.sender());
self.largest_block_size =
max(self.largest_block_size, worker_options.block_size);
socket = Box::new(single_socket);
} else {
socket = Box::new(create_multi_socket(&self.socket.local_addr()?, to)?);
}
socket.set_read_timeout(worker_options.timeout)?;
socket.set_write_timeout(worker_options.timeout)?;
self.clients.insert(*to, socket.sender());
self.largest_block_size =
max(self.largest_block_size, worker_options.block_size);
accept_request(&socket, options, RequestType::Write)?;
let worker = Worker::new(
@ -210,22 +204,6 @@ impl Server {
worker_options.window_size,
);
worker.receive()
} else {
let socket = create_multi_socket(&self.socket.local_addr()?, to)?;
socket.set_read_timeout(Some(worker_options.timeout))?;
socket.set_write_timeout(Some(worker_options.timeout))?;
accept_request(&socket, options, RequestType::Write)?;
let worker = Worker::new(
socket,
file_path.clone(),
worker_options.block_size,
worker_options.timeout,
worker_options.window_size,
);
worker.receive()
}
}
_ => Err("Unexpected error code when checking file".into()),
}

View file

@ -12,9 +12,8 @@ use crate::Packet;
const DEFAULT_TIMEOUT: Duration = Duration::from_secs(5);
/// Socket `trait` is used for easy message transmission of common TFTP
/// message types. This `trait` is implemented for [`UdpSocket`] and used
/// for abstraction of single socket communication.
/// Socket `trait` is used to allow building custom sockets to be used for
/// TFTP communication.
pub trait Socket: Send + Sync + 'static {
/// Sends a [`Packet`] to the socket's connected remote [`Socket`].
fn send(&self, packet: &Packet) -> Result<(), Box<dyn Error>>;
@ -165,6 +164,36 @@ impl ServerSocket {
}
}
impl<T: Socket + ?Sized> Socket for Box<T> {
fn send(&self, packet: &Packet) -> Result<(), Box<dyn Error>> {
(**self).send(packet)
}
fn send_to(&self, packet: &Packet, to: &SocketAddr) -> Result<(), Box<dyn Error>> {
(**self).send_to(packet, to)
}
fn recv(&self, buf: &mut [u8]) -> Result<Packet, Box<dyn Error>> {
(**self).recv(buf)
}
fn recv_from(&self, buf: &mut [u8]) -> Result<(Packet, SocketAddr), Box<dyn Error>> {
(**self).recv_from(buf)
}
fn remote_addr(&self) -> Result<SocketAddr, Box<dyn Error>> {
(**self).remote_addr()
}
fn set_read_timeout(&mut self, dur: Duration) -> Result<(), Box<dyn Error>> {
(**self).set_read_timeout(dur)
}
fn set_write_timeout(&mut self, dur: Duration) -> Result<(), Box<dyn Error>> {
(**self).set_write_timeout(dur)
}
}
#[cfg(test)]
mod tests {
use super::*;

View file

@ -5,9 +5,9 @@ use std::{
io::{Read, Write},
};
/// Window `struct` is used to store chunks of data from a file.
/// It is used to store the data that is being sent or received for
/// Windowsize option.
/// Window `struct` is used to store chunks of data from a file. It is
/// used to help store the data that is being sent or received for the
/// [RFC 7440](https://www.rfc-editor.org/rfc/rfc7440) Windowsize option.
///
/// # Example
/// ```rust
@ -206,8 +206,10 @@ mod tests {
.unwrap()
}
#[allow(unused_must_use)]
fn clean(file_name: &str) {
let file_name = DIR_NAME.to_string() + "/" + file_name;
fs::remove_file(file_name).unwrap();
fs::remove_dir(DIR_NAME);
}
}

View file

@ -28,7 +28,7 @@ const TIMEOUT_BUFFER: Duration = Duration::from_secs(1);
/// socket.connect(SocketAddr::from_str("127.0.0.1:12345").unwrap()).unwrap();
///
/// let worker = Worker::new(
/// socket,
/// Box::new(socket),
/// PathBuf::from_str("Cargo.toml").unwrap(),
/// 512,
/// Duration::from_secs(1),
@ -37,24 +37,18 @@ const TIMEOUT_BUFFER: Duration = Duration::from_secs(1);
///
/// worker.send().unwrap();
/// ```
pub struct Worker<T>
where
T: Socket,
{
socket: T,
pub struct Worker<T: Socket + ?Sized> {
socket: Box<T>,
file_name: PathBuf,
blk_size: usize,
timeout: Duration,
windowsize: u16,
}
impl<T> Worker<T>
where
T: Socket,
{
impl<T: Socket + ?Sized> Worker<T> {
/// Creates a new [`Worker`] with the supplied options.
pub fn new(
socket: T,
socket: Box<T>,
file_name: PathBuf,
blk_size: usize,
timeout: Duration,