#!/bin/bash
#Include all the config variables
source config
#
function add_file_to_list {
#multiple entries of the same file, with different hashs means that it is split into several encoded files
#can be greatly improved
size_file_compressed=$(stat -c %s $2) #provides size in bytes
size_file_compressed=$(echo "$size_file_compressed"|bc) #convert in B
echo "$2 $size_file_compressed $new_file_name" >> $master_file
cat $master_file | uniq > tmp
mv tmp $master_file
printf "$login_id\n$pass_id\nREGISTER_NEW_FILE\n$2\n$size_file_compressed\n" | socat - TCP:$server_ip:$server_port
}
function generate_file_name {
name_encoded_file=$(echo -n "$login_id$1" | md5sum | cut -f 1 -d " ")
echo NAME::::: $name_encoded_file >&2
echo $name_encoded_file
}
function calculate_pseudo_md5_file {
#because the md depends on the name, it is necessary to fix it.
#echo MD5---- >&2
mv $1 tmp_md5
md5=$(echo -n "$login $1" | md5sum | cut -f 1 -d " ")
mv tmp_md5 $1
#echo MD5----$md5 >&2
echo $md5
}
function get_hash_from_file {
line=$(cat $master_file | cut -d " " -f 3 | grep -Fxn "$1"|cut -d ":" -f 1)
for i in $line;
do
echo $(awk 'NR == '$i' {print; exit}' $master_file)|cut -d " " -f 1 >> $2
done
}
#Note that the file name must be unique
function upload_file {
echo upload_file $1
echo compressing file
new_file_name=$(echo $1 | sed -e "s/..\///g")
#echo $new_file_name
tar cz $1 | openssl enc -pass pass:$pass_files -aes-256-cbc -e > tmp
new_file_name_=$(calculate_pseudo_md5_file $1)
#echo $new_file_name_
mv tmp $new_file_name_
add_file_to_list "$1" "$new_file_name_"
peer_1=$(tail -n 1 active_peers.txt | cut -f 1)
peer_1_port=$(tail -n 1 active_peers.txt | cut -f 2)
printf "SEND_FILE\n$new_file_name_\n$size_file_compressed\n" | socat - TCP:$peer_1:$peer_1_port
aux=$(printf "REQUEST_FILES_PORT" | socat - TCP:$peer_1:$peer_1_port | tail -n 1)
socat -u FILE:$new_file_name_ TCP:$peer_1:$aux
#cat $(generate_file_name $new_file_name) | nc -u $peer_1 $aux
echo can implement md5 to verify if file is trully ok before deleting
rm $new_file_name_
}
function retrieve_active_peers {
printf "$login_id\n$pass_id\nGET_ACTIVE_PEERS" | socat - TCP:$server_ip:$server_port > active_peers.txt
}
function retrieve_netstats {
printf "$login_id\n$pass_id\nQUERY_NETWORK_STATISTICS\n" | socat - TCP:$server_ip:$server_port > tmp
cat tmp
rm tmp
}
function register_client_in_server {
echo register in server. Must check if available disk space is inferior to the one shared.
printf "$login_id\n$pass_id\nREGISTER_IN_SERVER\nIP:$external_ip\nport:$external_port_listening\nshared space:$shared_folder_size\n" | socat - TCP:$server_ip:$server_port > tmp
echo
cat tmp
}
function authenticate_in_server {
echo user
echo login
read result
}
function select_best_peer {
echo "Need to improve the selection of the peer"
best_peer=$(echo $1|cut -d " " -f 1)
}
function download_file {
#echo download_file
get_hash_from_file $1 "hash_codes_from_file.tmp"
s=$(cat "hash_codes_from_file.tmp")
rm "hash_codes_from_file.tmp"
#for each component of the file, retrieve the correspondent file
for i in $s
do
tmp=$(printf "$login_id\n$pass_id\nQUERY_ACTIVE_PEERS_FILE\n$i\n" | socat - TCP:$server_ip:$server_port)
tmp=$(echo $tmp|cut -d " " -f 6-)
#echo $tmp
select_best_peer $tmp
#enable port to listen in background
socat -u TCP-LISTEN:$external_port_listening_files,reuseaddr OPEN:"$download_folder/$i",creat,trunc &
proc=$!
printf "RETRIEVE_FILE\n$i\n$external_ip\n$external_port_listening_files\n" | socat - TCP:$best_peer
#wait for the server to send the file and finish the transaction
wait $proc
#receive file
echo "must implement timeouts. They are not in place"
#echo Decode the file $i
cat $download_folder/$i | openssl enc -pass pass:$pass_files -aes-256-cbc -d > tmp
mv tmp $download_folder/$i
done
#uncompress the file
#cat | openssl enc -pass pass:password -aes-256-cbc -d > tmp
echo "Uncompressing file(s) in $i: "
tar -zxvf $download_folder/$i -C $download_folder/
#echo "If split in multiple files must verify the outcome."--------------------------------------------------------
#delete all temporary files
for i in $s
do
#echo $s
#echo i
rm $download_folder/$i
done
}
function start_client_listener {
socat TCP-LISTEN:$external_port_listening,reuseaddr,fork EXEC:"$location_of_program -serve_client"
}
function register_new_login {
echo Contacting server...
printf "REQUEST_NEW_LOGIN\n$1\n$2\n" | socat - TCP:$server_ip:$server_port
echo Do not forget to change the configuration accordingly!
}
function check_available_serving_space {
echo $(du -s $shared_folder|cut -f 1)
}
function receive_file {
echo receive file >&2
echo "must verify if file exists in server before accepting it" >&2
read file_name
read file_size
free_space=$(df -P $shared_folder | tail -1 | awk '{print $4}')
#echo "$shared_folder_size - $(du -s $shared_folder|cut -f 1) > $file_size " >&2
#echo "$free_space > $file_size" >&2
if [[ ($(echo "$shared_folder_size - $(du -s $shared_folder|cut -f 1) > $file_size "|bc) -eq 1) && ($(echo "$free_space*1000 > $file_size"|bc) -eq 1) ]]; then
echo Accepting file. >&2
else
echo File receive refused. >&2
exit
fi
socat -u TCP-LISTEN:$external_port_listening_files,reuseaddr OPEN:"$shared_folder/$file_name",creat,trunc && cat "$shared_folder/file_name"
}
function request_file_port {
echo $external_port_listening_files
}
function retrieve_file {
#echo "Retrieve File ...................................."
read file_hash_name
read requester_ip
read requester_port
#echo file_requested: $file_hash_name
#echo requester_IP: $requester_ip
#echo requester_port: $requester_port
socat -u FILE:$shared_folder/$file_hash_name TCP:$requester_ip:$requester_port
echo OK
}
function handle_request {
read command
case "$command" in
SEND_FILE)
receive_file
;;
REQUEST_FILES_PORT)
request_file_port
;;
RETRIEVE_FILE)
retrieve_file
;;
*)
echo ERROR_COMMAND
esac
}
case "$1" in
-newlogin)
echo "Registering new login $2 $3"
register_new_login $2 $3
;;
-s)
register_client_in_server
echo starting client listener... on port:$external_port_listening
start_client_listener
exit
;;
-serve_client)
echo "handle request"
handle_request
;;
-u)
echo "upload file: $2"
upload_file "$2"
;;
-d)
echo "download file"
retrieve_active_peers
download_file "$2"
;;
-stats)
echo "retrieving network stats"
retrieve_netstats
;;
-?)
echo help!!!!!!!!!
echo '
./client [arg]
Configurations are stored in the file config and should be set according your system.
[args]
-newlogin [login] [password]
Creates a new user login
login - proposed login
-stats
Retrive the network statistics
-u file
uploads the file
-d file
downloads the file to defined path, in configurations
Visit the program project page: https://sourceforge.net/p/comunity-nas/'
;;
*)
echo "Command error: $0 $@"
./client.sh -?
esac