diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml
index db94fa1..46a2f6a 100644
--- a/.github/workflows/dev.yml
+++ b/.github/workflows/dev.yml
@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v3
- name: Build
run: cargo build --release --verbose
- name: Run tests
diff --git a/.github/workflows/pr_main.yml b/.github/workflows/pr_main.yml
index 8ac36d2..db4e60d 100644
--- a/.github/workflows/pr_main.yml
+++ b/.github/workflows/pr_main.yml
@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v3
- name: Build
run: cargo build --release --verbose
- name: Run tests
@@ -25,7 +25,7 @@ jobs:
runs-on: windows-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v3
- name: Build
run: cargo build --release --verbose
- name: Run tests
@@ -37,7 +37,7 @@ jobs:
runs-on: macos-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v3
- name: Build
run: cargo build --release --verbose
- name: Run tests
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index e2611ed..58c0fab 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -2,95 +2,99 @@ name: Rust -> Build & Test & Release
on:
push:
- branches: ["main"]
+ branches: [ "main" ]
env:
CARGO_TERM_COLOR: always
- PROJECT_NAME: ${{ github.event.repository.name }}
jobs:
build_linux:
+
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - name: Build
- run: cargo build --release --verbose
- - name: Run tests
- run: cargo test --verbose
+ - uses: actions/checkout@v3
+ - name: Build
+ run: cargo build --release --verbose
+ - name: Run tests
+ run: cargo test --verbose
- - name: Upload Linux Binary
- uses: actions/upload-artifact@v4
- with:
- name: ${{ env.PROJECT_NAME }}-linux-x64_86
- path: target/release/${{ env.PROJECT_NAME }}
+ - name: Upload Linux Binary
+ uses: actions/upload-artifact@v3
+ with:
+ name: rust_tcp_file_transfer_linux_x64_86
+ path: target/release/*transfer
build_windows:
+
runs-on: windows-latest
steps:
- - uses: actions/checkout@v4
- - name: Build
- run: cargo build --release --verbose
- - name: Run tests
- run: cargo test --verbose
+ - uses: actions/checkout@v3
+ - name: Build
+ run: cargo build --release --verbose
+ - name: Run tests
+ run: cargo test --verbose
- - name: Upload Windows Binary
- uses: actions/upload-artifact@v4
- with:
- name: ${{ env.PROJECT_NAME }}-windows-x64_86
- path: target/release/${{ env.PROJECT_NAME }}.exe
+ - name: Upload Windows Binary
+ uses: actions/upload-artifact@v3
+ with:
+ name: rust_tcp_file_transfer_windows_x64_86
+ path: target/release/*transfer.exe
build_macos:
+
runs-on: macos-latest
steps:
- - uses: actions/checkout@v4
- - name: Build
- run: cargo build --release --verbose
- - name: Run tests
- run: cargo test --verbose
+ - uses: actions/checkout@v3
+ - name: Build
+ run: cargo build --release --verbose
+ - name: Run tests
+ run: cargo test --verbose
- - name: Upload MacOS Binary
- uses: actions/upload-artifact@v4
- with:
- name: ${{ env.PROJECT_NAME }}-macos-arm64
- path: target/release/${{ env.PROJECT_NAME }}
+ - name: Upload MacOS Binary
+ uses: actions/upload-artifact@v3
+ with:
+ name: rust_tcp_file_transfer_macos_x64_86
+ path: target/release/*transfer
release:
needs: [build_linux, build_windows, build_macos]
runs-on: ubuntu-latest
- permissions:
- contents: write
+ permissions:
+ contents: write
steps:
- - uses: actions/checkout@v4
- - name: Forge a Folder
- run: mkdir Downloads
- working-directory: /home/runner/work/${{ env.PROJECT_NAME }}/${{ env.PROJECT_NAME }}/
- - uses: actions/download-artifact@v4
- name: Download
- with:
- path: Downloads/
+ - uses: actions/checkout@v3
+ - name: Forge a Folder
+ run: mkdir Downloads
+ working-directory: /home/runner/work/rust-tcp-file-transfer/rust-tcp-file-transfer/
- - name: Rename Binaries
- run: |
- tree Downloads/
- mv Downloads/${{ env.PROJECT_NAME }}-linux-x64_86/${{ env.PROJECT_NAME }} Downloads/${{ env.PROJECT_NAME }}-linux-x64_86/${{ env.PROJECT_NAME }}-linux-x64_86
- mv Downloads/${{ env.PROJECT_NAME }}-windows-x64_86/${{ env.PROJECT_NAME }}.exe Downloads/${{ env.PROJECT_NAME }}-windows-x64_86/${{ env.PROJECT_NAME }}-windows-x64_86.exe
- mv Downloads/${{ env.PROJECT_NAME }}-macos-arm64/${{ env.PROJECT_NAME }} Downloads/${{ env.PROJECT_NAME }}-macos-arm64/${{ env.PROJECT_NAME }}-macos-arm64
- - name: Git Commit SHA
- id: vars
- run: |
- calculatedSha=$(git rev-parse --short ${{ github.sha }})
- echo "short_sha=$calculatedSha" >> $GITHUB_OUTPUT
+ - uses: actions/download-artifact@v3
+ name: Download
+ with:
+ path: Downloads/
+
+ - name: Rename Binaries
+ run: |
+ mv Downloads/rust_tcp_file_transfer_linux_x64_86/rust-tcp-file-transfer Downloads/rust_tcp_file_transfer_linux_x64_86/rust-tcp-file-transfer-linux_x64_86
+ mv Downloads/rust_tcp_file_transfer_windows_x64_86/rust-tcp-file-transfer.exe Downloads/rust_tcp_file_transfer_windows_x64_86/rust-tcp-file-transfer-windows_x64_86.exe
+ mv Downloads/rust_tcp_file_transfer_macos_x64_86/rust-tcp-file-transfer Downloads/rust_tcp_file_transfer_macos_x64_86/rust-tcp-file-transfer-macos_x64_86
- - uses: softprops/action-gh-release@v2
- name: Release
- with:
- tag_name: ${{ steps.vars.outputs.short_sha }}
- generate_release_notes: true
- files: |
- Downloads/*linux*/${{ env.PROJECT_NAME }}*
- Downloads/*windows*/${{ env.PROJECT_NAME }}*
- Downloads/*macos*/${{ env.PROJECT_NAME }}*
+ - name: Git Commit SHA
+ id: vars
+ run: |
+ calculatedSha=$(git rev-parse --short ${{ github.sha }})
+ echo "short_sha=$calculatedSha" >> $GITHUB_OUTPUT
+
+ - uses: softprops/action-gh-release@v0.1.15
+ name: Release
+ with:
+ tag_name: ${{ steps.vars.outputs.short_sha }}
+ generate_release_notes: true
+ files: |
+ Downloads/*linux*/*transfer*
+ Downloads/*windows*/*transfer*
+ Downloads/*macos*/*transfer*
+
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 32d71ea..196e176 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,7 +2,6 @@
# will have compiled files and executables
debug/
target/
-.vscode/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
diff --git a/Cargo.toml b/Cargo.toml
index f4a5455..bec9c30 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,10 +8,6 @@ strip = "symbols"
opt-level = 3
overflow-checks = true
lto = true
-codegen-units = 1
-panic = "abort"
-
-[lints.rust]
-unsafe_code = "forbid"
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
diff --git a/README.md b/README.md
index b80f7bd..8bf8d1d 100644
--- a/README.md
+++ b/README.md
@@ -2,25 +2,16 @@
# rust-tcp-file-transfer
TCP File Transfer Server and Client in Rust
-**Usage**
-> ./rust-tcp-file-transfer -h
->
-
-
-
-**Examples**
-> ./rust-tcp-file-transfer -sv -s -l ~/Desktop/cat.png
->
-> ./rust-tcp-file-transfer -cl -r -l ~/Documents/
-
-
-
-**TO-DO List**
-
-☑ Standard library only.
-
☑ File transfer over network.
☑ Remove memory limitations. [d42412c](https://github.com/Tahinli/rust-tcp-file-transfer/pull/1/commits/d42412c57d7d95672ba64b3e489b95f1c4b04a08)
☑ Bidirectional transfer. [b0531de](https://github.com/Tahinli/rust-tcp-file-transfer/commit/b0531deb257332f46fc76de16d3a17fb3b28acee)
+
+☐ Folder transfer.
+
+☐ Remember where it stopped.
+
+☐ Reach over NAT (peer to peer).
+
+☐ Async.
diff --git a/assets/example.png b/assets/example.png
deleted file mode 100644
index c7f3952..0000000
Binary files a/assets/example.png and /dev/null differ
diff --git a/assets/help_menu.png b/assets/help_menu.png
deleted file mode 100644
index 311613f..0000000
Binary files a/assets/help_menu.png and /dev/null differ
diff --git a/src/main.rs b/src/main.rs
index 41d3a98..f0d1a85 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,729 +1,792 @@
-use std::env::{self};
-use std::fs::{self, File, Metadata};
-use std::io::{BufWriter, Read, Write};
-use std::net::{IpAddr, TcpListener, TcpStream};
+use std::fs::{File, Metadata, self};
use std::path::{Path, PathBuf};
use std::time::Instant;
+use std::net::{TcpListener, TcpStream, IpAddr};
+use std::io::{Read, Write, BufWriter, BufReader, BufRead};
+use std::env::{self};
-const BUFFER_SIZE: u64 = 100000;
+
+const BUFFER_SIZE:u64 = 100000;
#[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!()
- }
- }
+struct UserEnvironment
+ {
+ ip:IpAddr,
+ port:u16,
+ server:bool,
+ send:bool,
+ location:Option,
+ debug:bool,
+ }
+impl UserEnvironment
+ {
+ fn user_environment() -> UserEnvironment
+ {
+ UserEnvironment
+ {
+ ip:"127.0.0.1".parse().unwrap(),
+ port:2121,
+ server:false,
+ send:false,
+ location:None,
+ debug:false,
+ }
+ }
}
-}
#[derive(Debug)]
-struct UserEnvironment {
- ip: IpAddr,
- port: u16,
- server: bool,
- send: bool,
- location: Option,
- debug: bool,
-}
-impl UserEnvironment {
- fn new() -> UserEnvironment {
- UserEnvironment {
- ip: "127.0.0.1".parse().unwrap(),
- port: 2121,
- server: false,
- send: false,
- location: None,
- debug: false,
- }
+struct FileInfo
+ {
+ file:Option,
+ location:Option,
+ sign:Option,
+ size_total:u64,
+ size_current:u64,
+ metadata:Option,
+ progress:u8,
}
-}
-#[derive(Debug)]
-struct FileInfo {
- file: Option,
- location: Option,
- sign: Option,
- size_total: u64,
- size_current: u64,
- metadata: Option,
- progress: u8,
-}
-impl FileInfo {
- fn new() -> FileInfo {
- 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();
- }
- 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);
- self.send_file(stream, &(101_u8), debug_mode);
- } 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()
- );
- }
+impl FileInfo
+ {
+ fn file_info() -> FileInfo
+ {
+ FileInfo
+ {
+ file: None,
+ location: None,
+ sign: None,
+ size_total: 0,
+ size_current: 0,
+ metadata: None,
+ progress: 0
}
- None => {
- println!(
- "Error: Read Metadata -> {}",
- self.location.as_ref().unwrap()
- );
+ }
+ fn pass_user_environment(&mut self, user_environment:&UserEnvironment)
+ {
+ self.location = user_environment.location.clone();
+ self.sign = user_environment.location.clone();
+ }
+ 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");
+ return;
+ //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);
+ self.send_file(stream, &(101 as u8),debug_mode);
+ }
+
+ 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");
+ return;
+ //self.open_file(debug_mode);
+ //self.send_file(stream, &(102 as u8),debug_mode);
+ }
+ else
+ {
+ println!("Error: Undefined Type -> {}", self.location.as_ref().unwrap());
+ return;
+ }
+ }
+ None =>
+ {
+ println!("Error: Read Metadata -> {}", self.location.as_ref().unwrap());
+ }
+ }
+ }
+ None =>
+ {
+ println!("Error: Reading Operations -> {:#?}", &self.location);
+ panic!();
+ }
}
- }
}
- None => {
- println!("Error: Reading Operations -> {:#?}", &self.location);
- panic!();
+ fn writing_operations(&mut self, stream:&mut TcpStream, debug_mode:&bool)
+ {
+ self.write_file(stream, debug_mode);
+ self.cleaning();
}
- }
- }
- fn writing_operations(&mut self, stream: &mut TcpStream, debug_mode: &bool) {
- self.write_file(stream, debug_mode);
- self.cleaning();
- }
- 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
- );
- }
+ fn cleaning(&mut self)
+ {
+ self.location = self.sign.clone();
+ self.size_current = 0;
}
- } else {
- match fs::metadata(self.location.as_ref().unwrap()) {
- Ok(metadata) => {
- self.metadata = Some(metadata);
- if *debug_mode {
- println!("Done: Read Metadata -> {:#?}", self.metadata);
+ 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);
+ }
+ }
+ }
+ else
+ {
+ match fs::metadata(&self.location.as_ref().unwrap())
+ {
+ Ok(metadata) =>
+ {
+ self.metadata = Some(metadata);
+ if *debug_mode
+ {
+ println!("Done: Read Metadata -> {:#?}", self.metadata);
+ }
+ }
+ Err(err_val) =>
+ {
+ println!("Error: Read Metadata -> {} | Error: {}", &self.location.as_ref().unwrap(), err_val);
+ }
+ }
}
- }
- Err(err_val) => {
- println!(
- "Error: Read Metadata -> {} | Error: {}",
- &self.location.as_ref().unwrap(),
- err_val
- );
- }
}
- }
+ 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);
+ }
+ }
+ Err(err_val) =>
+ {
+ println!("Error: Open File -> {} | Error: {}", self.location.as_ref().unwrap(), err_val);
+ return;
+ }
+ }
+
+ }
+ 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);
+ }
+ 101 =>
+ {
+ if *debug_mode
+ {
+ println!("Done: File Detected -> {}", self.location.as_ref().unwrap());
+ }
+ self.callback_validation(stream, &String::from("101"), debug_mode)
+ }
+ 102 =>
+ {
+ if *debug_mode
+ {
+ println!("Done: Folder Detected -> {}", self.location.as_ref().unwrap());
+ }
+ self.callback_validation(stream, &String::from("102"), debug_mode)
+ }
+ _ =>
+ {
+
+ println!("Error: Undefined Type Detected ->{}", self.location.as_ref().unwrap());
+ return;
+
+ }
+ }
+ 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);
+ }
+ if *debug_mode
+ {
+ println!("Read Data = {:#?}", buffer);
+ }
+ self.send_exact(&mut buffer, stream, debug_mode);
+ self.show_progress(iteration, total_iteration);
+ }
+ }
+ fn callback_validation(&mut self, stream:&mut TcpStream, data:&String, debug_mode:&bool)
+ {
+ self.send_exact(String::from(data.clone() + "\n").as_bytes(), stream, debug_mode);
+ match self.recv_until(stream, '\n', debug_mode)
+ {
+ Some(callback_callback) =>
+ {
+ if callback_callback == data.to_string().as_bytes().to_vec()
+ {
+ if *debug_mode
+ {
+ println!("Done: Callback -> {}", self.location.as_ref().unwrap());
+ println!("{:#?} ", callback_callback);
+ }
+ }
+ else
+ {
+ println!("Error: Callback -> {}", self.location.as_ref().unwrap());
+ println!("{:#?} ", callback_callback);
+ panic!()
+ }
+ }
+ None =>
+ {
+ panic!()
+ }
+ }
+ }
+ 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);
+ }
+ }
+ Err(err_val) =>
+ {
+ println!("Error: Read Bytes -> {} | Error: {}", self.location.as_ref().unwrap(), err_val);
+ panic!()
+ }
+ }
+ }
+ 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!()
+ }
+ }
+ }
+ 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);
+ }
+ }
+ Err(err_val) =>
+ {
+ println!("Error: Receive Bytes -> {:#?} | Error: {}", self.location, err_val);
+ panic!();
+ }
+ }
+ }
+ fn recv_until(&mut self, stream:&mut TcpStream, until:char, debug_mode:&bool) -> Option>
+ {
+ let mut buffer = Vec::new();
+ let mut stream_reader = BufReader::new(stream.try_clone().unwrap());
+ match stream_reader.read_until(until as u8,&mut buffer)
+ {
+ Ok(_) =>
+ {
+ if *debug_mode
+ {
+ println!("Done: Receive Until -> {:#?}", self.location);
+ println!("{:#?}", buffer);
+ }
+ buffer.pop();
+ }
+ Err(err_val) =>
+ {
+ println!("Error: Receive Until -> {:#?} | Error: {}", self.location, err_val);
+ return None;
+ }
+ }
+ return Some(buffer);
+ }
+ 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
+ {
+ match self.recv_until(stream, '\n', debug_mode)
+ {
+ Some(mut callback) =>
+ {
+
+ if *debug_mode
+ {
+ println!("Done: Callback -> {:#?}", self.location);
+ println!("{:#?} ", callback);
+ }
+ let data = String::from_utf8(callback.clone()).unwrap();
+ callback.push(b'\n');
+ self.send_exact(&callback.as_slice(), stream, debug_mode);
+ data
+ }
+ None =>
+ {
+ println!("Error: Callback -> {:#?}", self.location);
+ panic!();
+ }
+ }
+ }
+ 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);
+ }
+ }
+ 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)
+ {
+ let what_type:u8 = self.callback_recv(stream, debug_mode).parse().unwrap();
+ self.size_total = self.callback_recv(stream, debug_mode).parse().unwrap();
+ let location:String = self.callback_recv(stream, debug_mode);
+ match what_type
+ {
+ 100 =>
+ {
+ if *debug_mode
+ {
+ println!("Done: Symlink Detected -> {}", self.location.as_ref().unwrap());
+ }
+ self.forge_file( location, debug_mode);
+ return;
+ }
+ 101 =>
+ {
+ if *debug_mode
+ {
+ println!("Done: File Detected -> {}", self.location.as_ref().unwrap());
+ }
+ self.forge_file(location, debug_mode);
+ }
+ 102 =>
+ {
+ if *debug_mode
+ {
+ println!("Done: Folder Detected -> {}", self.location.as_ref().unwrap());
+ }
+ self.forge_file(location, debug_mode);
+ }
+ _ =>
+ {
+ println!("Error: Undefined Type -> {}", self.location.as_ref().unwrap());
+ return;
+ }
+ }
+ self.open_file(debug_mode);
+ let mut iteration:u64 = (&self.size_total/BUFFER_SIZE)+1;
+ 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(&buffer[..(&self.size_total%BUFFER_SIZE) as usize], debug_mode);
+ }
+ self.show_progress(iteration, total_iteration);
+ }
+ }
+ 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);
+ }
+ }
+ fn show_progress(&mut self, iteration:u64, total_iteration:u64)
+ {
+ if iteration%10 == 0
+ {
+ let progress:u8 = 100 as u8 - ((iteration as f64/total_iteration as f64)*100 as f64)as u8;
+ if progress != self.progress
+ {
+ self.progress = progress;
+ println!("%{}", self.progress);
+ }
+ }
+
+ }
}
- fn open_file(&mut self, debug_mode: &bool) {
- match File::options()
- .read(true)
- .write(true)
- .open(self.location.as_ref().unwrap())
+enum Connection
+ {
+ Server(String, String),
+ Client(String, String),
+ }
+
+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;
+ }
+ }
+ }
+ }
+ 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);
+ }
+ }
+
+ }
+ }
+fn send_or_receive(file_info:&mut FileInfo, stream:&mut TcpStream, debug_mode:&bool, user_environment:&UserEnvironment)
+ {
+ match user_environment.send
{
- Ok(file) => {
- self.file = Some(file);
- if *debug_mode {
- println!("Done : Open File -> {:#?}", self.file);
+ true =>
+ {
+ let start_time = Instant::now();
+ FileInfo::reading_operations(file_info, stream, &debug_mode);
+ let finish_time = Instant::now();
+ println!("Done: Transfer");
+ println!("Passed: Total -> {:#?}", finish_time.duration_since(start_time));
+ }
+ false =>
+ {
+ let start_time = Instant::now();
+ FileInfo::writing_operations(file_info, stream, &debug_mode);
+ let finish_time = Instant::now();
+ println!("Done: Transfer");
+ println!("Passed: Total -> {:#?}", finish_time.duration_since(start_time));
}
- }
- Err(err_val) => {
- println!(
- "Error: Open File -> {} | Error: {}",
- self.location.as_ref().unwrap(),
- err_val
- );
- }
}
}
- 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);
- }
- 101 => {
- if *debug_mode {
- println!("Done: File Detected -> {}", self.location.as_ref().unwrap());
- }
- self.callback_validation(stream, &String::from("101"), debug_mode)
- }
- 102 => {
- if *debug_mode {
- println!(
- "Done: Folder Detected -> {}",
- self.location.as_ref().unwrap()
- );
- }
- self.callback_validation(stream, &String::from("102"), debug_mode)
- }
- _ => {
- println!(
- "Error: Undefined Type Detected ->{}",
- self.location.as_ref().unwrap()
- );
- return;
- }
- }
- 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,
- );
+fn take_args(mut user_environment:UserEnvironment) -> Option
+ {
+ let env_args:Vec = 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;
+ }
+ "--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;
+ }
+ "--help" | "-h" =>
+ {
+ show_help();
+ return None;
- 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,
- );
- }
- if *debug_mode {
- println!("Read Data = {:#?}", buffer);
- }
- self.send_exact(&buffer, stream, debug_mode);
- self.show_progress(iteration, total_iteration);
- }
+ }
+ err =>
+ {
+ println!("Error: Invalid Argument, You Gave {}", err);
+ return None;
+ }
+ }
+ i += 1;
+ }
+ Some(user_environment)
}
- fn callback_validation(&mut self, stream: &mut TcpStream, data: &String, debug_mode: &bool) {
- let mut data_vec: Vec = data.as_bytes().to_vec();
- let mut terminator_vec: Vec = vec![b'\n'; BUFFER_SIZE as usize - data_vec.len()];
- data_vec.append(&mut terminator_vec);
- drop(terminator_vec);
- let mut data_exact: [u8; BUFFER_SIZE as usize] = [b'\n'; BUFFER_SIZE as usize];
- data_exact.swap_with_slice(data_vec[..].as_mut());
- drop(data_vec);
- self.send_exact(&data_exact, stream, debug_mode);
- let mut data_exact_check: [u8; BUFFER_SIZE as usize] = [b'\n'; BUFFER_SIZE as usize];
- 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);
- }
- } else {
- println!("Error: Callback -> {}", self.location.as_ref().unwrap());
- println!("{:#?} ", data_exact_check);
- panic!()
- }
+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 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);
- }
+fn main()
+ {
+ //DONT FORGET
+ //First we should check folder structure and validation then make connection.
+ //Until's can be deprecated, 100k byte should be enough for eveything.(Security)
+ println!("Hello, world!");
+ let mut file_info:FileInfo = FileInfo::file_info();
+ let user_environment:UserEnvironment;
+ match take_args(UserEnvironment::user_environment())
+ {
+ Some(usr_env) =>
+ {
+ user_environment = usr_env;
+ }
+ None =>
+ {
+ return;
+ }
}
- Err(err_val) => {
- println!(
- "Error: Read Bytes -> {} | Error: {}",
- self.location.as_ref().unwrap(),
- err_val
- );
- panic!()
+ 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);
+ }
}
- }
}
- 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!()
- }
- }
- }
- 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);
- }
- }
- Err(err_val) => {
- println!(
- "Error: Receive Bytes -> {:#?} | Error: {}",
- self.location, err_val
- );
- panic!();
- }
- }
- }
- 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 {
- 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);
- }
- self.send_exact(&buffer, stream, debug_mode);
- data
- }
- 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);
- }
- }
- 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) {
- let what_type: FileType = FileType::what_type(
- self.callback_recv(stream, debug_mode)
- .parse::()
- .unwrap(),
- self,
- debug_mode,
- );
- self.size_total = self.callback_recv(stream, debug_mode).parse().unwrap();
- let location: String = self.callback_recv(stream, debug_mode);
- self.file_forger(what_type, location, debug_mode);
- self.open_file(debug_mode);
- let mut iteration: u64 = (self.size_total / BUFFER_SIZE) + 1;
- 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(
- &buffer[..(self.size_total % BUFFER_SIZE) as usize],
- debug_mode,
- );
- }
- self.show_progress(iteration, total_iteration);
- }
- }
- 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);
- }
- }
- }
- 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);
- }
- }
- fn show_progress(&mut self, iteration: u64, total_iteration: u64) {
- if iteration % 10 == 0 {
- let progress: u8 =
- 100_u8 - ((iteration as f64 / total_iteration as f64) * 100_f64) as u8;
- if progress != self.progress {
- self.progress = progress;
- println!("%{}", self.progress);
- }
- }
- }
-}
-enum Connection {
- Server(String, String),
- Client(String, String),
-}
-
-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;
- }
- }
- }
- }
- 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);
- }
- }
- }
-}
-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();
- FileInfo::reading_operations(file_info, stream, debug_mode);
- let finish_time = Instant::now();
- println!("Done: Transfer");
- println!(
- "Passed: Total -> {:#?}",
- finish_time.duration_since(start_time)
- );
- }
- false => {
- let start_time = Instant::now();
- FileInfo::writing_operations(file_info, stream, debug_mode);
- 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 {
- let env_args: Vec = 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;
- }
- "--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;
- }
- "--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!");
- let mut file_info: FileInfo = FileInfo::new();
- let user_environment: UserEnvironment = match take_args(UserEnvironment::new()) {
- Some(usr_env) => usr_env,
- None => {
- return;
- }
- };
- 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,
- );
- }
- }
-}