feat: create tftpc binary

This commit is contained in:
Pierre Tardy 2024-07-01 19:38:52 +02:00 committed by Altuğ Bakan
parent fb3a684f28
commit 7a6be5e9b5
6 changed files with 58 additions and 66 deletions

View file

@ -17,5 +17,9 @@ jobs:
- uses: actions/checkout@v3
- name: Build
run: cargo build --verbose
- name: Build
run: cargo build --features client --verbose
- name: Run tests
run: cargo test --verbose
- name: test client
run: cargo test --features client --verbose

View file

@ -9,6 +9,15 @@ license = "MIT"
keywords = ["tftp", "server"]
categories = ["command-line-utilities"]
[[bin]]
name = "tftpc"
path = "src/client_main.rs"
required-features = ["client"]
[[bin]]
name = "tftpd"
path = "src/main.rs"
[features]
integration = []
client = []

View file

@ -34,28 +34,22 @@ tftpd -i 0.0.0.0 -p 1234 -d "/home/user/tftp" -r
## Usage (Client)
Client code is protected by a feature flag names `client`.
To install the client and server using Cargo:
```bash
cargo install --features client tftpd
tftpd client --help
tftpd server --help
```
To run the server on the IP address `0.0.0.0`, read-only, on port `1234` in the `/home/user/tftp` directory:
```bash
tftpd server -i 0.0.0.0 -p 1234 -d "/home/user/tftp" -r
tftpc --help
```
To connect the client to a tftp server running on IP address `127.0.0.1`, read-only, on port `1234` and download a file named `example.file`
```bash
tftpd client example.file -i 0.0.0.0 -p 1234 -d
tftpc example.file -i 0.0.0.0 -p 1234 -d
```
To connect the client to a tftp server running on IP address `127.0.0.1`, read-only, on port `1234` and upload a file named `example.file`
```bash
tftpd client ./example.file -i 0.0.0.0 -p 1234 -u
tftpc ./example.file -i 0.0.0.0 -p 1234 -u
```
## License

View file

@ -55,8 +55,8 @@ impl Client {
})
}
/// Starts the Client depending on the [`Mode`] the client is in
pub fn start(&mut self) -> Result<(), Box<dyn Error>> {
/// Run the Client depending on the [`Mode`] the client is in
pub fn run(&mut self) -> Result<(), Box<dyn Error>> {
match self.mode {
Mode::Upload => self.upload(),
Mode::Download => self.download(),

39
src/client_main.rs Normal file
View file

@ -0,0 +1,39 @@
use std::error::Error;
use std::env::args;
use std::{env, net::SocketAddr, process};
use tftpd::{Client, ClientConfig, Config, Mode, Server};
fn main() {
let args: Vec<String> = env::args().collect();
client(args[0..].iter().map(|s| s.to_string())).unwrap_or_else(|err| {
eprintln!("{err}");
})
}
fn client<T: Iterator<Item = String>>(args: T) -> Result<(), Box<dyn Error>> {
let config = ClientConfig::new(args).unwrap_or_else(|err| {
eprintln!("Problem parsing arguments: {err}");
process::exit(1)
});
let mut client = Client::new(&config).unwrap_or_else(|err| {
eprintln!("Problem creating client: {err}");
process::exit(1)
});
if config.mode == Mode::Upload {
println!(
"Starting TFTP Client, uploading {} to {}",
config.filename.display(),
SocketAddr::new(config.remote_ip_address, config.port),
);
} else {
println!(
"Starting TFTP Client, downloading {} to {}",
config.filename.display(),
SocketAddr::new(config.remote_ip_address, config.port),
);
}
client.run()
}

View file

@ -1,65 +1,11 @@
#[cfg(feature = "client")]
use std::error::Error;
use std::{env, net::SocketAddr, process};
#[cfg(not(feature = "client"))]
use tftpd::{Config, Server};
#[cfg(feature = "client")]
use tftpd::{Client, ClientConfig, Config, Mode, Server};
#[cfg(feature = "client")]
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
eprintln!("{}: incorrect usage", args[0]);
eprintln!("{} <client | server> [args]", args[0]);
} else if args[1] == "client" {
client(args[1..].iter().map(|s| s.to_string())).unwrap_or_else(|err| {
eprintln!("{err}");
})
} else if args[1] == "server" {
server(args[1..].iter().map(|s| s.to_string()));
} else {
eprintln!("{}: incorrect usage", args[0]);
eprintln!("{} (client | server) [args]", args[0]);
}
}
#[cfg(not(feature = "client"))]
fn main() {
let args: Vec<String> = env::args().collect();
server(args[0..].iter().map(|s| s.to_string()));
}
#[cfg(feature = "client")]
fn client<T: Iterator<Item = String>>(args: T) -> Result<(), Box<dyn Error>> {
let config = ClientConfig::new(args).unwrap_or_else(|err| {
eprintln!("Problem parsing arguments: {err}");
process::exit(1)
});
let mut server = Client::new(&config).unwrap_or_else(|err| {
eprintln!("Problem creating client: {err}");
process::exit(1)
});
if config.mode == Mode::Upload {
println!(
"Starting TFTP Client, uploading {} to {}",
config.filename.display(),
SocketAddr::new(config.remote_ip_address, config.port),
);
} else {
println!(
"Starting TFTP Client, downloading {} to {}",
config.filename.display(),
SocketAddr::new(config.remote_ip_address, config.port),
);
}
server.start()
}
fn server<T: Iterator<Item = String>>(args: T) {
let config = Config::new(args).unwrap_or_else(|err| {
eprintln!("Problem parsing arguments: {err}");