diff --git a/src/client/authd_api.cr b/src/client/authd_api.cr new file mode 100644 index 0000000..5e2cda9 --- /dev/null +++ b/src/client/authd_api.cr @@ -0,0 +1,14 @@ + +def authd_get_token(key_file : String? = nil, login : String? = nil, pass : String? = nil) + + authd = AuthD::Client.new + key_file.try do |file| # FIXME: fail if missing? + authd.key = File.read(file).chomp + end + + token = authd.get_token? login, pass + raise "cannot get a token" if token.nil? + authd.close + + token +end diff --git a/src/client/main.cr b/src/client/main.cr index 5fadce6..e577bd2 100644 --- a/src/client/main.cr +++ b/src/client/main.cr @@ -1,10 +1,16 @@ require "option_parser" +require "authd" require "ipc" require "json" require "base64" -require "../common/filestorage.cr" +require "./authd_api.cr" +require "../server/network.cr" +require "../server/storage.cr" +require "../server/storage/*" +require "../common/*" +require "../common/requests/*" # TODO # For now, this example only upload files. @@ -14,9 +20,8 @@ service_name = "filestorage" files_and_directories_to_transfer = Array(String).new -# This is the requests we will send to the server -upload_requests = Array(FileStorage::UploadRequest).new - +authd_login : String = "test" +authd_pass : String = "test" OptionParser.parse do |parser| parser.on "-s service-name", @@ -25,6 +30,18 @@ OptionParser.parse do |parser| service_name = name end + parser.on "-l login", + "--login login-name", + "Login name for authd." do |name| + authd_login = name + end + + parser.on "-p pass", + "--pass pass", + "Password for authd." do |pass| + authd_pass = pass + end + parser.unknown_args do |arg| files_and_directories_to_transfer = arg end @@ -32,18 +49,16 @@ OptionParser.parse do |parser| parser.on "-h", "--help", "Show this help" do puts parser puts "program [OPTIONS] " - exit 0 + exit -1 end end # -# Get informations about files to transfer -# For now, we only want to upload files, so we create an UploadRequest +# Verify we can read files # -files_info = Hash(String, FileStorage::FileInfo).new - +files = [] of String puts "files and directories to transfer" files_and_directories_to_transfer.each do |f| @@ -51,9 +66,7 @@ files_and_directories_to_transfer.each do |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 + files << f else if ! File.exists? f puts "#{f} does not exist" @@ -65,101 +78,24 @@ files_and_directories_to_transfer.each do |f| end end -files_info.values.each do |file_info| - upload_requests << FileStorage::UploadRequest.new file_info -end - -# pp! upload_requests - # # Connection to the service # -client = IPC::Client.new service_name +# Authentication. +pp! authd_login +pp! authd_pass +token = authd_get_token login: authd_login, pass: authd_pass -# -# Sending the authentication message, including files info -# +# Connection and authentication to filestoraged. +client = FileStorage::Client.new token, service_name +client.login -token = FileStorage::Token.new 1002, "karchnu" -authentication_message = FileStorage::Authentication.new token, upload_requests -pp! authentication_message -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 = FileStorage::Response.from_json(String.new m.payload) - -if response.mid == authentication_message.mid - puts "This is a response for the authentication message" - pp! response -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 = 0 - size = 0 - - while (size = file.read(buffer)) > 0 - # transfer message = file_info, chunk count, data (will be base64'd) - transfer_message = FileStorage::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 - - - # Check for the response - m = client.read - mtype = FileStorage::MessageType.new m.utype.to_i32 - if mtype != FileStorage::MessageType::Response - pp! m - raise "Message received was not expected: #{mtype}" - end - - response = FileStorage::Response.from_json(String.new m.payload) - - if response.mid != transfer_message.mid - raise "Message received has a wrong mid: #{response.mid} != #{transfer_message.mid}" - else - pp! response - end - 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 +files.each do |file| + puts "upload: #{file}" + pp! client.upload file + puts "transfer" + client.transfer file 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 diff --git a/src/common/requests/client.cr b/src/common/requests/client.cr index d12d875..322107e 100644 --- a/src/common/requests/client.cr +++ b/src/common/requests/client.cr @@ -1,64 +1,106 @@ +require "ipc" -class FileStorage::Client +class FileStorage::Client < IPC::Client + property auth_token : String - def login(token : String) - request = FileStorage::Request::Login.new token + def initialize(@auth_token, service_name = "filestorage") + super service_name + end + + def login + request = FileStorage::Request::Login.new auth_token send request - response = parse_message [ FileStorage::Response::Login, FileStorage::Response::Error ], read + response = parse_message [ + FileStorage::Response::Login, + FileStorage::Errors::GenericError + ], read - case response - when FileStorage::Response::Login - # Received favorites, likes, etc. - when FileStorage::Response::Error - raise "user was not logged in: #{response.reason}" + if response.responds_to? :mid + if request.mid != response.mid + raise "mid from response != request" + end + else + raise "response doen't even have mid" end response end - def transfer(file_info : FileInfo, count, bindata) - request = FileStorage::Request::PutChunk.new file_info, count, bindata - send request + def get_file_info(file_path : String) + file_info : FileStorage::FileInfo + file = File.open(file_path) + file_info = FileStorage::FileInfo.new file + file.close + file_info.not_nil! + end - response = parse_message [ FileStorage::Response::PutChunk, FileStorage::Response::Error ], read + def transfer(file_path : String) + file_info = get_file_info file_path - case response - when FileStorage::Response::PutChunk - when FileStorage::Response::Error - raise "File chunk was not transfered: #{response.reason}" + File.open(file_path) do |file| + buffer_size = FileStorage.message_buffer_size + + buffer = Bytes.new buffer_size + counter = 0 + size = 0 + + while (size = file.read(buffer)) > 0 + puts "loop !!!" + # transfer message = file_info, chunk count, data (will be base64'd) + transfer_message = FileStorage::Request::PutChunk.new file_info, + counter, + buffer[0 ... size] + + send transfer_message + counter += 1 + + buffer = Bytes.new buffer_size + + # Check for the response + response = parse_message [ + FileStorage::Response::PutChunk, + FileStorage::Errors::GenericError + ], read + + if response.responds_to? :mid + if response.mid != transfer_message.mid + raise "request and response mid !=: #{response.mid} != #{transfer_message.mid}" + else + pp! response + end + else + raise "response doesn't have mid" + end + end end - - response end def download(filedigest = nil, name = nil, tags = nil) request = FileStorage::Request::Download.new filedigest, name, tags send request - response = parse_message [ FileStorage::Response::Download, FileStorage::Response::Error ], read - - case response - when FileStorage::Response::Download - when FileStorage::Response::Error - raise "Download request denied: #{response.reason}" - end + response = parse_message [ + FileStorage::Response::Download, + FileStorage::Errors::GenericError + ], read response end - def upload(token : String) - request = FileStorage::Request::Upload.new token - send request - - response = parse_message [ FileStorage::Response::Upload, FileStorage::Response::Error ], read - - case response - when FileStorage::Response::Upload - when FileStorage::Response::Error - raise "Upload request failed: #{response.reason}" + def upload(file : String) + file_info : FileStorage::FileInfo + File.open(file) do |f| + file_info = FileStorage::FileInfo.new f + request = FileStorage::Request::Upload.new file_info + send request end + response = parse_message [ + FileStorage::Response::Upload, + FileStorage::Errors::GenericError + ], read + response end end diff --git a/src/server/storage.cr b/src/server/storage.cr index 487a7ed..23a0d6d 100644 --- a/src/server/storage.cr +++ b/src/server/storage.cr @@ -46,7 +46,7 @@ class FileStorage::Storage # - users/ : DODB UserData (for later use: quotas, rights) def initialize(@root) - @db = DODB::DataBase(TransferInfo).new "'#{@root}/meta" + @db = DODB::DataBase(TransferInfo).new "#{@root}/meta" # Where to store uploaded files. FileUtils.mkdir_p "#{@root}/files" diff --git a/src/structures b/src/structures index 28db681..8606069 100644 --- a/src/structures +++ b/src/structures @@ -19,6 +19,8 @@ class FileStorage::FileInfo nb_chunks : Int32 digest : String tags : Array(String) + + initialize(file : File, tags = nil) end class TransferInfo @@ -35,7 +37,8 @@ class FileStorage::UserData property uploads : Array(Upload) # NOT USED. property downloads : Array(Download) # NOT USED. - initialize(@uid, @uploads = Array(Upload).new, @downloads = Array(Download).new) + initialize(@uid, @uploads = Array(Upload).new, + @downloads = Array(Download).new) end root/