2024-03-02 17:56:38 +03:00
|
|
|
use std::env::{self};
|
|
|
|
use std::fs::{self, File, Metadata};
|
2024-03-03 01:42:39 +03:00
|
|
|
use std::io::{BufWriter, Read, Write};
|
2024-03-02 17:56:38 +03:00
|
|
|
use std::net::{IpAddr, TcpListener, TcpStream};
|
2023-10-30 00:48:25 +03:00
|
|
|
use std::path::{Path, PathBuf};
|
2023-09-17 07:28:18 +03:00
|
|
|
use std::time::Instant;
|
2023-10-20 22:21:06 +03:00
|
|
|
|
2024-03-02 17:56:38 +03:00
|
|
|
const BUFFER_SIZE: u64 = 100000;
|
2023-10-30 00:48:25 +03:00
|
|
|
|
2024-03-03 03:24:15 +03:00
|
|
|
#[derive(Debug)]
|
|
|
|
enum FileType {
|
|
|
|
Symlink,
|
|
|
|
File,
|
|
|
|
Folder,
|
|
|
|
}
|
|
|
|
impl FileType {
|
|
|
|
fn what_type(value: u8, file_info: &FileInfo, debug_mode: &bool) -> FileType {
|
|
|
|
match value {
|
|
|
|
100 => {
|
|
|
|
if *debug_mode {
|
|
|
|
println!(
|
|
|
|
"Done: Symlink Detected -> {}",
|
|
|
|
file_info.location.as_ref().unwrap()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
FileType::Symlink
|
|
|
|
}
|
|
|
|
101 => {
|
|
|
|
if *debug_mode {
|
|
|
|
println!(
|
|
|
|
"Done: File Detected -> {}",
|
|
|
|
file_info.location.as_ref().unwrap()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
FileType::File
|
|
|
|
}
|
|
|
|
102 => {
|
|
|
|
if *debug_mode {
|
|
|
|
println!(
|
|
|
|
"Done: Folder Detected -> {}",
|
|
|
|
file_info.location.as_ref().unwrap()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
FileType::Folder
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
println!(
|
|
|
|
"Error: Undefined Type -> {}",
|
|
|
|
file_info.location.as_ref().unwrap()
|
|
|
|
);
|
|
|
|
panic!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-10-30 00:48:25 +03:00
|
|
|
#[derive(Debug)]
|
2024-03-02 17:56:38 +03:00
|
|
|
struct UserEnvironment {
|
|
|
|
ip: IpAddr,
|
|
|
|
port: u16,
|
|
|
|
server: bool,
|
|
|
|
send: bool,
|
|
|
|
location: Option<String>,
|
|
|
|
debug: bool,
|
|
|
|
}
|
|
|
|
impl UserEnvironment {
|
2024-03-02 18:31:41 +03:00
|
|
|
fn new() -> UserEnvironment {
|
2024-03-02 17:56:38 +03:00
|
|
|
UserEnvironment {
|
|
|
|
ip: "127.0.0.1".parse().unwrap(),
|
|
|
|
port: 2121,
|
|
|
|
server: false,
|
|
|
|
send: false,
|
|
|
|
location: None,
|
|
|
|
debug: false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct FileInfo {
|
|
|
|
file: Option<File>,
|
|
|
|
location: Option<String>,
|
|
|
|
sign: Option<String>,
|
|
|
|
size_total: u64,
|
|
|
|
size_current: u64,
|
|
|
|
metadata: Option<Metadata>,
|
|
|
|
progress: u8,
|
|
|
|
}
|
|
|
|
impl FileInfo {
|
2024-03-02 18:31:41 +03:00
|
|
|
fn new() -> FileInfo {
|
2024-03-02 17:56:38 +03:00
|
|
|
FileInfo {
|
|
|
|
file: None,
|
|
|
|
location: None,
|
|
|
|
sign: None,
|
|
|
|
size_total: 0,
|
|
|
|
size_current: 0,
|
|
|
|
metadata: None,
|
|
|
|
progress: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn pass_user_environment(&mut self, user_environment: &UserEnvironment) {
|
|
|
|
self.location = user_environment.location.clone();
|
|
|
|
self.sign = user_environment.location.clone();
|
2023-10-30 00:48:25 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
fn reading_operations(&mut self, stream: &mut TcpStream, debug_mode: &bool) {
|
|
|
|
match self.location.as_ref() {
|
|
|
|
Some(_) => {
|
|
|
|
self.read_metadata(debug_mode);
|
|
|
|
match self.metadata {
|
|
|
|
Some(ref mut metadata) => {
|
|
|
|
if Metadata::is_symlink(metadata) {
|
|
|
|
//Unix-Windows Problem
|
|
|
|
println!("\n\tError: Symlink Transfers've not Supported yet\n");
|
|
|
|
//self.open_file(debug_mode);
|
|
|
|
//self.send_file(stream, &(100 as u8),debug_mode);
|
|
|
|
} else if Metadata::is_file(metadata) {
|
|
|
|
self.open_file(debug_mode);
|
2024-03-02 18:31:41 +03:00
|
|
|
self.send_file(stream, &(101_u8), debug_mode);
|
2024-03-02 17:56:38 +03:00
|
|
|
} else if Metadata::is_dir(metadata) {
|
|
|
|
//path recognition and creation on the other side
|
|
|
|
//std:path
|
|
|
|
println!("\n\tError: Folder Transfers've not Supported yet\n");
|
|
|
|
//self.open_file(debug_mode);
|
|
|
|
//self.send_file(stream, &(102 as u8),debug_mode);
|
|
|
|
} else {
|
|
|
|
println!(
|
|
|
|
"Error: Undefined Type -> {}",
|
|
|
|
self.location.as_ref().unwrap()
|
|
|
|
);
|
|
|
|
}
|
2023-10-31 13:54:26 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
None => {
|
|
|
|
println!(
|
|
|
|
"Error: Read Metadata -> {}",
|
|
|
|
self.location.as_ref().unwrap()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2023-10-31 13:54:26 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
None => {
|
|
|
|
println!("Error: Reading Operations -> {:#?}", &self.location);
|
|
|
|
panic!();
|
|
|
|
}
|
|
|
|
}
|
2023-10-31 13:54:26 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
fn writing_operations(&mut self, stream: &mut TcpStream, debug_mode: &bool) {
|
|
|
|
self.write_file(stream, debug_mode);
|
|
|
|
self.cleaning();
|
2023-09-14 08:29:32 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
fn cleaning(&mut self) {
|
|
|
|
self.location = self.sign.clone();
|
|
|
|
self.size_current = 0;
|
|
|
|
}
|
|
|
|
fn read_metadata(&mut self, debug_mode: &bool) {
|
|
|
|
let path = PathBuf::from(self.location.as_ref().unwrap());
|
|
|
|
if path.is_symlink() {
|
|
|
|
match path.symlink_metadata() {
|
|
|
|
Ok(metadata) => {
|
|
|
|
self.metadata = Some(metadata);
|
|
|
|
}
|
|
|
|
Err(err_val) => {
|
|
|
|
println!(
|
|
|
|
"Error: Symlink Metadata -> {:#?} | Error: {}",
|
|
|
|
&self.location, err_val
|
|
|
|
);
|
|
|
|
}
|
2023-10-31 13:54:26 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
} else {
|
2024-03-02 18:31:41 +03:00
|
|
|
match fs::metadata(self.location.as_ref().unwrap()) {
|
2024-03-02 17:56:38 +03:00
|
|
|
Ok(metadata) => {
|
|
|
|
self.metadata = Some(metadata);
|
|
|
|
if *debug_mode {
|
|
|
|
println!("Done: Read Metadata -> {:#?}", self.metadata);
|
2023-10-08 01:52:42 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
}
|
|
|
|
Err(err_val) => {
|
|
|
|
println!(
|
|
|
|
"Error: Read Metadata -> {} | Error: {}",
|
|
|
|
&self.location.as_ref().unwrap(),
|
|
|
|
err_val
|
|
|
|
);
|
|
|
|
}
|
2023-09-29 01:44:25 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
fn open_file(&mut self, debug_mode: &bool) {
|
|
|
|
match File::options()
|
|
|
|
.read(true)
|
|
|
|
.write(true)
|
|
|
|
.open(self.location.as_ref().unwrap())
|
|
|
|
{
|
|
|
|
Ok(file) => {
|
|
|
|
self.file = Some(file);
|
|
|
|
if *debug_mode {
|
|
|
|
println!("Done : Open File -> {:#?}", self.file);
|
|
|
|
}
|
2023-10-02 22:04:41 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
Err(err_val) => {
|
|
|
|
println!(
|
|
|
|
"Error: Open File -> {} | Error: {}",
|
|
|
|
self.location.as_ref().unwrap(),
|
|
|
|
err_val
|
|
|
|
);
|
2023-10-13 03:12:51 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
fn send_file(&mut self, stream: &mut TcpStream, what_type: &u8, debug_mode: &bool) {
|
|
|
|
self.size_total = self.metadata.as_ref().unwrap().len();
|
|
|
|
let mut iteration = (self.size_total / BUFFER_SIZE) + 1;
|
|
|
|
let total_iteration = iteration;
|
|
|
|
let path_buf = PathBuf::from(Path::new(self.location.as_ref().unwrap()));
|
|
|
|
match what_type {
|
|
|
|
100 => {
|
|
|
|
if *debug_mode {
|
|
|
|
println!(
|
|
|
|
"Done: Symlink Detected -> {}",
|
|
|
|
self.location.as_ref().unwrap()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
self.callback_validation(stream, &String::from("100"), debug_mode);
|
2023-10-13 03:12:51 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
101 => {
|
|
|
|
if *debug_mode {
|
|
|
|
println!("Done: File Detected -> {}", self.location.as_ref().unwrap());
|
|
|
|
}
|
|
|
|
self.callback_validation(stream, &String::from("101"), debug_mode)
|
2023-10-13 03:12:51 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
102 => {
|
|
|
|
if *debug_mode {
|
|
|
|
println!(
|
|
|
|
"Done: Folder Detected -> {}",
|
|
|
|
self.location.as_ref().unwrap()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
self.callback_validation(stream, &String::from("102"), debug_mode)
|
2023-09-16 19:15:30 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
_ => {
|
|
|
|
println!(
|
|
|
|
"Error: Undefined Type Detected ->{}",
|
|
|
|
self.location.as_ref().unwrap()
|
|
|
|
);
|
|
|
|
return;
|
2023-10-13 03:12:51 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
}
|
|
|
|
self.callback_validation(stream, &(self.size_total.to_string()), debug_mode);
|
|
|
|
self.callback_validation(
|
|
|
|
stream,
|
|
|
|
&path_buf.file_name().unwrap().to_str().unwrap().to_string(),
|
|
|
|
debug_mode,
|
|
|
|
);
|
|
|
|
|
|
|
|
self.show_info(&iteration, debug_mode);
|
|
|
|
while iteration != 0 {
|
|
|
|
iteration -= 1;
|
|
|
|
let mut buffer = [0u8; BUFFER_SIZE as usize];
|
|
|
|
if iteration != 0 {
|
|
|
|
self.read_exact(&mut buffer, debug_mode);
|
|
|
|
} else {
|
|
|
|
self.read_exact(
|
|
|
|
&mut buffer[..(self.size_total % BUFFER_SIZE) as usize],
|
|
|
|
debug_mode,
|
|
|
|
);
|
2023-10-31 02:53:42 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
if *debug_mode {
|
|
|
|
println!("Read Data = {:#?}", buffer);
|
2023-10-13 03:12:51 +03:00
|
|
|
}
|
2024-03-02 18:31:41 +03:00
|
|
|
self.send_exact(&buffer, stream, debug_mode);
|
2024-03-02 17:56:38 +03:00
|
|
|
self.show_progress(iteration, total_iteration);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn callback_validation(&mut self, stream: &mut TcpStream, data: &String, debug_mode: &bool) {
|
2024-03-03 01:42:39 +03:00
|
|
|
let mut data_vec: Vec<u8> = data.as_bytes().to_vec();
|
|
|
|
let mut terminator_vec: Vec<u8> = vec![b'\n'; BUFFER_SIZE as usize - data_vec.len()];
|
|
|
|
data_vec.append(&mut terminator_vec);
|
|
|
|
drop(terminator_vec);
|
2024-03-03 03:24:15 +03:00
|
|
|
let mut data_exact: [u8; BUFFER_SIZE as usize] = [b'\n'; BUFFER_SIZE as usize];
|
|
|
|
data_exact.swap_with_slice(data_vec[..].as_mut());
|
2024-03-03 01:42:39 +03:00
|
|
|
drop(data_vec);
|
|
|
|
self.send_exact(&data_exact, stream, debug_mode);
|
2024-03-03 03:24:15 +03:00
|
|
|
let mut data_exact_check: [u8; BUFFER_SIZE as usize] = [b'\n'; BUFFER_SIZE as usize];
|
2024-03-03 01:42:39 +03:00
|
|
|
self.recv_exact(&mut data_exact_check, stream, debug_mode);
|
|
|
|
if data_exact_check == data_exact {
|
|
|
|
if *debug_mode {
|
|
|
|
println!("Done: Callback -> {}", self.location.as_ref().unwrap());
|
|
|
|
println!("{:#?} ", data_exact_check);
|
2023-10-13 03:12:51 +03:00
|
|
|
}
|
2024-03-03 01:42:39 +03:00
|
|
|
} else {
|
|
|
|
println!("Error: Callback -> {}", self.location.as_ref().unwrap());
|
|
|
|
println!("{:#?} ", data_exact_check);
|
|
|
|
panic!()
|
2024-03-02 17:56:38 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
fn read_exact(&mut self, buffer: &mut [u8], debug_mode: &bool) {
|
|
|
|
match self.file.as_ref().unwrap().read_exact(buffer) {
|
|
|
|
Ok(_) => {
|
|
|
|
if *debug_mode {
|
|
|
|
println!("Done: Read Bytes -> {}", self.location.as_ref().unwrap());
|
|
|
|
println!("{:#?}", buffer);
|
|
|
|
}
|
2023-10-31 02:53:42 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
Err(err_val) => {
|
|
|
|
println!(
|
|
|
|
"Error: Read Bytes -> {} | Error: {}",
|
|
|
|
self.location.as_ref().unwrap(),
|
|
|
|
err_val
|
|
|
|
);
|
|
|
|
panic!()
|
2023-10-31 02:53:42 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
}
|
2023-09-14 08:29:32 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
fn send_exact(&mut self, buffer: &[u8], stream: &mut TcpStream, debug_mode: &bool) {
|
|
|
|
let mut stream_writer = BufWriter::new(stream.try_clone().unwrap());
|
|
|
|
match stream_writer.write_all(buffer) {
|
|
|
|
Ok(_) => {
|
|
|
|
self.size_current += buffer.len() as u64;
|
|
|
|
if *debug_mode {
|
|
|
|
println!("Done: Send Bytes -> {:#?}", self.location);
|
|
|
|
println!("{:#?}", buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(err_val) => {
|
|
|
|
println!(
|
|
|
|
"Error: Send Bytes -> {:#?} | Error: {}",
|
|
|
|
self.location, err_val
|
|
|
|
);
|
|
|
|
panic!();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
match stream_writer.flush() {
|
|
|
|
Ok(_) => {
|
|
|
|
if *debug_mode {
|
|
|
|
println!("Done: Flush -> {:#?}", self.location);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(err_val) => {
|
|
|
|
println!("Error: Flush -> {:#?} | Error: {}", self.location, err_val);
|
|
|
|
panic!()
|
|
|
|
}
|
|
|
|
}
|
2023-09-16 19:15:30 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
fn recv_exact(&mut self, buffer: &mut [u8], stream: &mut TcpStream, debug_mode: &bool) {
|
|
|
|
match stream.read_exact(buffer) {
|
|
|
|
Ok(_) => {
|
|
|
|
self.size_current += buffer.len() as u64;
|
|
|
|
if *debug_mode {
|
|
|
|
println!("Done: Receive Bytes -> {:#?}", self.location);
|
|
|
|
println!("{:#?}", buffer);
|
|
|
|
}
|
2023-09-16 19:15:30 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
Err(err_val) => {
|
|
|
|
println!(
|
|
|
|
"Error: Receive Bytes -> {:#?} | Error: {}",
|
|
|
|
self.location, err_val
|
|
|
|
);
|
|
|
|
panic!();
|
2023-09-14 08:29:32 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
}
|
2023-09-14 08:29:32 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
fn forge_file(&mut self, location: String, debug_mode: &bool) {
|
|
|
|
//dont forget
|
|
|
|
//directory recognition required for received location
|
|
|
|
match self.location.as_ref() {
|
|
|
|
Some(self_location) => {
|
|
|
|
let mut path = PathBuf::from(&self_location);
|
|
|
|
path.push(location);
|
|
|
|
self.forge_folder(self_location.clone(), debug_mode);
|
|
|
|
self.location = Some(path.to_str().unwrap().to_string());
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
self.location = Some(location);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
match File::create(self.location.as_ref().unwrap()) {
|
|
|
|
Ok(file) => {
|
|
|
|
if *debug_mode {
|
|
|
|
println!("Done Forge File -> {:#?}", file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(err_val) => {
|
|
|
|
println!(
|
|
|
|
"Error: Forge File -> {:#?} | Error: {}",
|
|
|
|
self.location.as_ref(),
|
|
|
|
err_val
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn forge_folder(&mut self, location: String, debug_mode: &bool) {
|
|
|
|
match fs::create_dir_all(&location) {
|
|
|
|
Ok(_) => {
|
|
|
|
if *debug_mode {
|
|
|
|
println!("Done: Forge Folder -> {}", &location);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(err_val) => {
|
|
|
|
println!("Error: Forge Folder -> {} | Error: {}", location, err_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn callback_recv(&mut self, stream: &mut TcpStream, debug_mode: &bool) -> String {
|
2024-03-03 01:42:39 +03:00
|
|
|
let mut buffer: [u8; BUFFER_SIZE as usize] = [0; BUFFER_SIZE as usize];
|
|
|
|
self.recv_exact(&mut buffer, stream, debug_mode);
|
|
|
|
if *debug_mode {
|
|
|
|
println!("Done: Callback -> {:#?}", self.location);
|
|
|
|
println!("{:#?} ", buffer);
|
|
|
|
}
|
|
|
|
let data = String::from_utf8(
|
|
|
|
buffer
|
|
|
|
.split(|element| *element == b'\n')
|
|
|
|
.next()
|
|
|
|
.unwrap()
|
|
|
|
.to_vec(),
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
if *debug_mode {
|
|
|
|
println!("Done: Split -> {:#?}", self.location);
|
|
|
|
println!("{:#?}", data);
|
2024-03-02 17:56:38 +03:00
|
|
|
}
|
2024-03-03 01:42:39 +03:00
|
|
|
self.send_exact(&buffer, stream, debug_mode);
|
|
|
|
data
|
2024-03-02 17:56:38 +03:00
|
|
|
}
|
|
|
|
fn save_exact(&mut self, buffer: &[u8], debug_mode: &bool) {
|
|
|
|
let mut file_writer = BufWriter::new(self.file.as_ref().unwrap());
|
|
|
|
if *debug_mode {
|
|
|
|
println!("{:#?}", file_writer);
|
|
|
|
}
|
|
|
|
match file_writer.write_all(buffer) {
|
|
|
|
Ok(_) => {
|
|
|
|
if *debug_mode {
|
|
|
|
println!(
|
|
|
|
"Done: Write -> {} | {} bytes",
|
|
|
|
self.location.as_ref().unwrap(),
|
|
|
|
self.size_current
|
|
|
|
);
|
|
|
|
println!("{:#?}", buffer);
|
2023-10-21 21:47:16 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
}
|
|
|
|
Err(err_val) => {
|
|
|
|
println!(
|
|
|
|
"Error: Write -> {} | Error: {}",
|
|
|
|
self.location.as_ref().unwrap(),
|
|
|
|
err_val
|
|
|
|
);
|
|
|
|
panic!();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
match file_writer.flush() {
|
|
|
|
Ok(_) => {
|
|
|
|
if *debug_mode {
|
|
|
|
println!("Done: Flush -> {}", self.location.as_ref().unwrap());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(err_val) => {
|
|
|
|
println!(
|
|
|
|
"Error: Flush -> {} | Error: {}",
|
|
|
|
self.location.as_ref().unwrap(),
|
|
|
|
err_val
|
|
|
|
);
|
|
|
|
panic!();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn write_file(&mut self, stream: &mut TcpStream, debug_mode: &bool) {
|
2024-03-03 03:24:15 +03:00
|
|
|
let what_type: FileType = FileType::what_type(
|
|
|
|
self.callback_recv(stream, debug_mode)
|
|
|
|
.parse::<u8>()
|
|
|
|
.unwrap(),
|
|
|
|
self,
|
|
|
|
debug_mode,
|
|
|
|
);
|
2024-03-02 17:56:38 +03:00
|
|
|
self.size_total = self.callback_recv(stream, debug_mode).parse().unwrap();
|
|
|
|
let location: String = self.callback_recv(stream, debug_mode);
|
2024-03-03 03:24:15 +03:00
|
|
|
self.file_forger(what_type, location, debug_mode);
|
2024-03-02 17:56:38 +03:00
|
|
|
self.open_file(debug_mode);
|
2024-03-02 18:31:41 +03:00
|
|
|
let mut iteration: u64 = (self.size_total / BUFFER_SIZE) + 1;
|
2024-03-02 17:56:38 +03:00
|
|
|
let total_iteration = iteration;
|
|
|
|
self.show_info(&iteration, debug_mode);
|
|
|
|
while iteration != 0 {
|
|
|
|
iteration -= 1;
|
|
|
|
let mut buffer = [0u8; BUFFER_SIZE as usize];
|
|
|
|
self.recv_exact(&mut buffer, stream, debug_mode);
|
|
|
|
if iteration != 0 {
|
|
|
|
self.save_exact(&buffer, debug_mode);
|
|
|
|
} else {
|
|
|
|
self.save_exact(
|
2024-03-02 18:31:41 +03:00
|
|
|
&buffer[..(self.size_total % BUFFER_SIZE) as usize],
|
2024-03-02 17:56:38 +03:00
|
|
|
debug_mode,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
self.show_progress(iteration, total_iteration);
|
|
|
|
}
|
|
|
|
}
|
2024-03-03 03:24:15 +03:00
|
|
|
fn file_forger(&mut self, file_type: FileType, location: String, debug_mode: &bool) {
|
|
|
|
match file_type {
|
|
|
|
FileType::Symlink => {
|
|
|
|
self.forge_file(location, debug_mode);
|
|
|
|
}
|
|
|
|
FileType::File => {
|
|
|
|
self.forge_file(location, debug_mode);
|
|
|
|
}
|
|
|
|
FileType::Folder => {
|
|
|
|
self.forge_file(location, debug_mode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
fn show_info(&mut self, iteration: &u64, debug_mode: &bool) {
|
|
|
|
println!("File = {}", self.location.as_ref().unwrap());
|
|
|
|
println!("Size = {}", self.size_total);
|
|
|
|
if *debug_mode {
|
|
|
|
println!("Iteration = {}", iteration);
|
2023-10-21 21:47:16 +03:00
|
|
|
}
|
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
fn show_progress(&mut self, iteration: u64, total_iteration: u64) {
|
|
|
|
if iteration % 10 == 0 {
|
|
|
|
let progress: u8 =
|
2024-03-02 18:31:41 +03:00
|
|
|
100_u8 - ((iteration as f64 / total_iteration as f64) * 100_f64) as u8;
|
2024-03-02 17:56:38 +03:00
|
|
|
if progress != self.progress {
|
|
|
|
self.progress = progress;
|
|
|
|
println!("%{}", self.progress);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
enum Connection {
|
|
|
|
Server(String, String),
|
|
|
|
Client(String, String),
|
|
|
|
}
|
2023-10-30 02:07:05 +03:00
|
|
|
|
2024-03-02 17:56:38 +03:00
|
|
|
impl Connection {
|
|
|
|
fn server(self, file_info: &mut FileInfo, user_environment: &UserEnvironment) {
|
|
|
|
print!("Server -> ");
|
|
|
|
if user_environment.debug {
|
|
|
|
println!("{:#?}", user_environment);
|
|
|
|
println!("{:#?}", file_info);
|
|
|
|
}
|
|
|
|
let ip: String;
|
|
|
|
let port: String;
|
|
|
|
let address: String;
|
|
|
|
match self {
|
|
|
|
Connection::Server(in1, in2) => {
|
|
|
|
ip = in1.trim_end().to_string();
|
|
|
|
port = in2.trim_end().to_string();
|
|
|
|
address = format!("{}:{}", ip, port);
|
|
|
|
println!("{}", address);
|
|
|
|
}
|
|
|
|
_ => return,
|
|
|
|
}
|
|
|
|
let socket = TcpListener::bind(address);
|
|
|
|
for stream in socket.expect("Error: Can't Check Connections").incoming() {
|
|
|
|
match stream {
|
|
|
|
Ok(mut stream) => {
|
|
|
|
println!("Connected");
|
|
|
|
send_or_receive(
|
|
|
|
file_info,
|
|
|
|
&mut stream,
|
|
|
|
&user_environment.debug,
|
|
|
|
user_environment,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
Err(e) => {
|
|
|
|
println!("Error: Can't Visit Stream -> {}", e);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-10-30 02:07:05 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
fn client(self, file_info: &mut FileInfo, user_environment: &UserEnvironment) {
|
|
|
|
print!("Client -> ");
|
|
|
|
if user_environment.debug {
|
|
|
|
println!("{:#?}", user_environment);
|
|
|
|
println!("{:#?}", file_info);
|
|
|
|
}
|
|
|
|
let ip: String;
|
|
|
|
let port: String;
|
|
|
|
let address: String;
|
|
|
|
match self {
|
|
|
|
Connection::Client(in1, in2) => {
|
|
|
|
ip = in1.trim_end().to_string();
|
|
|
|
port = in2.trim_end().to_string();
|
|
|
|
address = format!("{}:{}", ip, port);
|
|
|
|
println!("{}", address);
|
|
|
|
}
|
|
|
|
_ => return,
|
|
|
|
}
|
|
|
|
match TcpStream::connect(address) {
|
|
|
|
Ok(mut stream) => {
|
|
|
|
println!("Connected");
|
|
|
|
send_or_receive(
|
|
|
|
file_info,
|
|
|
|
&mut stream,
|
|
|
|
&user_environment.debug,
|
|
|
|
user_environment,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
Err(e) => {
|
|
|
|
println!("Error: Connection -> {}", e);
|
|
|
|
}
|
|
|
|
}
|
2023-10-17 14:51:29 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
}
|
|
|
|
fn send_or_receive(
|
|
|
|
file_info: &mut FileInfo,
|
|
|
|
stream: &mut TcpStream,
|
|
|
|
debug_mode: &bool,
|
|
|
|
user_environment: &UserEnvironment,
|
|
|
|
) {
|
|
|
|
match user_environment.send {
|
|
|
|
true => {
|
|
|
|
let start_time = Instant::now();
|
2024-03-02 18:31:41 +03:00
|
|
|
FileInfo::reading_operations(file_info, stream, debug_mode);
|
2024-03-02 17:56:38 +03:00
|
|
|
let finish_time = Instant::now();
|
|
|
|
println!("Done: Transfer");
|
|
|
|
println!(
|
|
|
|
"Passed: Total -> {:#?}",
|
|
|
|
finish_time.duration_since(start_time)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
false => {
|
|
|
|
let start_time = Instant::now();
|
2024-03-02 18:31:41 +03:00
|
|
|
FileInfo::writing_operations(file_info, stream, debug_mode);
|
2024-03-02 17:56:38 +03:00
|
|
|
let finish_time = Instant::now();
|
|
|
|
println!("Done: Transfer");
|
|
|
|
println!(
|
|
|
|
"Passed: Total -> {:#?}",
|
|
|
|
finish_time.duration_since(start_time)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn take_args(mut user_environment: UserEnvironment) -> Option<UserEnvironment> {
|
|
|
|
let env_args: Vec<String> = env::args().collect();
|
|
|
|
if env_args.len() > 16 {
|
|
|
|
println!(
|
|
|
|
"Error: Too Many Arguments, You Gave {} Arguments",
|
|
|
|
env_args.len()
|
|
|
|
);
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
let mut i = 1;
|
|
|
|
while i < env_args.len() {
|
|
|
|
match env_args[i].as_str() {
|
|
|
|
"--ip" | "-i" => {
|
|
|
|
user_environment.ip = env_args[i + 1].parse().unwrap();
|
|
|
|
i += 1;
|
2023-10-30 02:07:05 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
"--port" | "-p" => {
|
|
|
|
user_environment.port = env_args[i + 1].parse().unwrap();
|
|
|
|
i += 1;
|
|
|
|
}
|
|
|
|
"--location" | "-l" => {
|
|
|
|
user_environment.location = Some(env_args[i + 1].parse().unwrap());
|
|
|
|
i += 1;
|
|
|
|
}
|
|
|
|
"--server" | "-sv" => {
|
|
|
|
user_environment.server = true;
|
|
|
|
}
|
|
|
|
"--client" | "-cl" => {
|
|
|
|
user_environment.server = false;
|
|
|
|
}
|
|
|
|
"--send" | "-s" => {
|
|
|
|
user_environment.send = true;
|
|
|
|
}
|
|
|
|
"--receive" | "-r" => {
|
|
|
|
user_environment.send = false;
|
|
|
|
}
|
|
|
|
"--debug" | "-d" => {
|
|
|
|
user_environment.debug = true;
|
2023-09-16 19:15:30 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
"--help" | "-h" => {
|
|
|
|
show_help();
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
err => {
|
|
|
|
println!("Error: Invalid Argument, You Gave {}", err);
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
i += 1;
|
|
|
|
}
|
|
|
|
Some(user_environment)
|
|
|
|
}
|
|
|
|
fn show_help() {
|
|
|
|
println!("\n\n\n");
|
|
|
|
println!(" Arguments | Details | Defaults");
|
|
|
|
println!("----------------------------------------------------------------------");
|
|
|
|
println!(" -i -> --ip | Specifies IP Address | 127.0.0.1");
|
|
|
|
println!(" -p -> --port | Specifies Port Address | 2121");
|
|
|
|
println!(" -l -> --location | Specifies Location Address | Same as Program");
|
|
|
|
println!(" -sv -> --server | Starts as a Server | False");
|
|
|
|
println!(" -cl -> --client | Starts as a Client | True");
|
|
|
|
println!(" -s -> --send | Starts as a Sender | False");
|
|
|
|
println!(" -r -> --receive | Starts as a Receiver | True");
|
|
|
|
println!(" -d -> --debug | Starts in Debug Mode | False");
|
|
|
|
println!(" -h -> --help | Shows Help | False");
|
|
|
|
println!("\n\n\n");
|
|
|
|
}
|
|
|
|
fn main() {
|
|
|
|
//DONT FORGET
|
|
|
|
//First we should check folder structure and validation then make connection.
|
|
|
|
println!("Hello, world!");
|
2024-03-02 18:31:41 +03:00
|
|
|
let mut file_info: FileInfo = FileInfo::new();
|
|
|
|
let user_environment: UserEnvironment = match take_args(UserEnvironment::new()) {
|
|
|
|
Some(usr_env) => usr_env,
|
2024-03-02 17:56:38 +03:00
|
|
|
None => {
|
|
|
|
return;
|
|
|
|
}
|
2024-03-02 18:31:41 +03:00
|
|
|
};
|
2024-03-02 17:56:38 +03:00
|
|
|
file_info.pass_user_environment(&user_environment);
|
|
|
|
match user_environment.server {
|
|
|
|
true => {
|
|
|
|
Connection::server(
|
|
|
|
Connection::Server(
|
|
|
|
user_environment.ip.to_string(),
|
|
|
|
user_environment.port.to_string(),
|
|
|
|
),
|
|
|
|
&mut file_info,
|
|
|
|
&user_environment,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
false => {
|
|
|
|
Connection::client(
|
|
|
|
Connection::Client(
|
|
|
|
user_environment.ip.to_string(),
|
|
|
|
user_environment.port.to_string(),
|
|
|
|
),
|
|
|
|
&mut file_info,
|
|
|
|
&user_environment,
|
|
|
|
);
|
|
|
|
}
|
2023-09-14 08:29:32 +03:00
|
|
|
}
|
2024-03-02 17:56:38 +03:00
|
|
|
}
|