149 lines
3.1 KiB
Crystal
149 lines
3.1 KiB
Crystal
|
require "option_parser"
|
||
|
require "ipc"
|
||
|
require "json"
|
||
|
|
||
|
require "base64"
|
||
|
|
||
|
require "../common/filestorage.cr"
|
||
|
|
||
|
alias FM = FileStorage::Message
|
||
|
|
||
|
# TODO
|
||
|
# For now, this example only upload files.
|
||
|
# In a near future, we should be able to download files, too.
|
||
|
|
||
|
service_name = "filestorage"
|
||
|
|
||
|
files_and_directories_to_transfer = Array(String).new
|
||
|
|
||
|
# This is the requests we will send to the server
|
||
|
requests = Array(FM::Request).new
|
||
|
|
||
|
|
||
|
OptionParser.parse do |parser|
|
||
|
parser.on "-s service-name",
|
||
|
"--service-name service-name",
|
||
|
"Service name." do |name|
|
||
|
service_name = name
|
||
|
end
|
||
|
|
||
|
parser.unknown_args do |arg|
|
||
|
files_and_directories_to_transfer = arg
|
||
|
end
|
||
|
|
||
|
parser.on "-h", "--help", "Show this help" do
|
||
|
puts parser
|
||
|
puts "program [OPTIONS] <files-to-upload>"
|
||
|
exit 0
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
#
|
||
|
# Get informations about files to transfer
|
||
|
# For now, we only want to upload files, so we create an UploadRequest
|
||
|
#
|
||
|
|
||
|
files_info = Hash(String, FileStorage::FileInfo).new
|
||
|
|
||
|
|
||
|
puts "files and directories to transfer"
|
||
|
files_and_directories_to_transfer.each do |f|
|
||
|
if File.directory? f
|
||
|
# TODO
|
||
|
puts "Directories not supported, for now"
|
||
|
elsif File.file?(f) && File.readable? f
|
||
|
File.open(f) do |file|
|
||
|
files_info[file.path] = FileStorage::FileInfo.new file
|
||
|
end
|
||
|
else
|
||
|
if ! File.exists? f
|
||
|
puts "#{f} does not exist"
|
||
|
elsif ! File.file? f
|
||
|
puts "#{f} is neither a directory or a file"
|
||
|
elsif ! File.readable? f
|
||
|
puts "#{f} is not readable"
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
files_info.values.each do |file_info|
|
||
|
requests << FM::UploadRequest.new file_info
|
||
|
end
|
||
|
|
||
|
pp! requests
|
||
|
|
||
|
#
|
||
|
# Connection to the service
|
||
|
#
|
||
|
|
||
|
client = IPC::Client.new service_name
|
||
|
|
||
|
#
|
||
|
# Sending the authentication message, including files info
|
||
|
#
|
||
|
|
||
|
token = FileStorage::Token.new 1002, "karchnu"
|
||
|
authentication_message = FM::Authentication.new token, requests
|
||
|
client.send FileStorage::MessageType::Authentication.to_u8, authentication_message.to_json
|
||
|
|
||
|
#
|
||
|
# Receiving a response
|
||
|
#
|
||
|
|
||
|
m = client.read
|
||
|
# puts "message received: #{m.to_s}"
|
||
|
# puts "message received payload: #{String.new m.payload}"
|
||
|
|
||
|
response = FM::Response.from_json(String.new m.payload)
|
||
|
|
||
|
if response.mid == authentication_message.mid
|
||
|
puts "This is a response for the authentication message"
|
||
|
else
|
||
|
raise "Message IDs from authentication message and its response differ"
|
||
|
end
|
||
|
|
||
|
#
|
||
|
# file transfer
|
||
|
#
|
||
|
|
||
|
def file_transfer(client : IPC::Client, file : File, file_info : FileStorage::FileInfo)
|
||
|
buffer_size = 1_000
|
||
|
|
||
|
buffer = Bytes.new buffer_size
|
||
|
counter = 1
|
||
|
size = 0
|
||
|
|
||
|
while (size = file.read(buffer)) > 0
|
||
|
# transfer message = file_info, chunk count, data (will be base64'd)
|
||
|
transfer_message = FM::Transfer.new file_info, counter, buffer[0 ... size]
|
||
|
|
||
|
client.send FileStorage::MessageType::Transfer.to_u8, transfer_message.to_json
|
||
|
counter += 1
|
||
|
|
||
|
buffer = Bytes.new buffer_size
|
||
|
end
|
||
|
end
|
||
|
|
||
|
puts "transfer"
|
||
|
|
||
|
files_info.keys.each do |file_path|
|
||
|
puts "- #{file_path}"
|
||
|
|
||
|
File.open(file_path) do |file|
|
||
|
file_transfer client, file, files_info[file_path]
|
||
|
end
|
||
|
end
|
||
|
|
||
|
client.close
|
||
|
|
||
|
#client.loop do |event|
|
||
|
# case event
|
||
|
# when IPC::Event::Message
|
||
|
# puts "\033[32mthere is a message\033[00m"
|
||
|
# puts event.message.to_s
|
||
|
# client.close
|
||
|
# exit
|
||
|
# end
|
||
|
#end
|