Server fixes, and client is working.
This commit is contained in:
parent
761c12a0ba
commit
60b9d9fa01
14
src/client/authd_api.cr
Normal file
14
src/client/authd_api.cr
Normal file
@ -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
|
@ -1,10 +1,16 @@
|
|||||||
require "option_parser"
|
require "option_parser"
|
||||||
|
require "authd"
|
||||||
require "ipc"
|
require "ipc"
|
||||||
require "json"
|
require "json"
|
||||||
|
|
||||||
require "base64"
|
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
|
# TODO
|
||||||
# For now, this example only upload files.
|
# For now, this example only upload files.
|
||||||
@ -14,9 +20,8 @@ service_name = "filestorage"
|
|||||||
|
|
||||||
files_and_directories_to_transfer = Array(String).new
|
files_and_directories_to_transfer = Array(String).new
|
||||||
|
|
||||||
# This is the requests we will send to the server
|
authd_login : String = "test"
|
||||||
upload_requests = Array(FileStorage::UploadRequest).new
|
authd_pass : String = "test"
|
||||||
|
|
||||||
|
|
||||||
OptionParser.parse do |parser|
|
OptionParser.parse do |parser|
|
||||||
parser.on "-s service-name",
|
parser.on "-s service-name",
|
||||||
@ -25,6 +30,18 @@ OptionParser.parse do |parser|
|
|||||||
service_name = name
|
service_name = name
|
||||||
end
|
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|
|
parser.unknown_args do |arg|
|
||||||
files_and_directories_to_transfer = arg
|
files_and_directories_to_transfer = arg
|
||||||
end
|
end
|
||||||
@ -32,18 +49,16 @@ OptionParser.parse do |parser|
|
|||||||
parser.on "-h", "--help", "Show this help" do
|
parser.on "-h", "--help", "Show this help" do
|
||||||
puts parser
|
puts parser
|
||||||
puts "program [OPTIONS] <files-to-upload>"
|
puts "program [OPTIONS] <files-to-upload>"
|
||||||
exit 0
|
exit -1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Get informations about files to transfer
|
# Verify we can read files
|
||||||
# For now, we only want to upload files, so we create an UploadRequest
|
|
||||||
#
|
#
|
||||||
|
|
||||||
files_info = Hash(String, FileStorage::FileInfo).new
|
files = [] of String
|
||||||
|
|
||||||
|
|
||||||
puts "files and directories to transfer"
|
puts "files and directories to transfer"
|
||||||
files_and_directories_to_transfer.each do |f|
|
files_and_directories_to_transfer.each do |f|
|
||||||
@ -51,9 +66,7 @@ files_and_directories_to_transfer.each do |f|
|
|||||||
# TODO
|
# TODO
|
||||||
puts "Directories not supported, for now"
|
puts "Directories not supported, for now"
|
||||||
elsif File.file?(f) && File.readable? f
|
elsif File.file?(f) && File.readable? f
|
||||||
File.open(f) do |file|
|
files << f
|
||||||
files_info[file.path] = FileStorage::FileInfo.new file
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
if ! File.exists? f
|
if ! File.exists? f
|
||||||
puts "#{f} does not exist"
|
puts "#{f} does not exist"
|
||||||
@ -65,101 +78,24 @@ files_and_directories_to_transfer.each do |f|
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
files_info.values.each do |file_info|
|
|
||||||
upload_requests << FileStorage::UploadRequest.new file_info
|
|
||||||
end
|
|
||||||
|
|
||||||
# pp! upload_requests
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Connection to the service
|
# 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
|
||||||
|
|
||||||
#
|
# Connection and authentication to filestoraged.
|
||||||
# Sending the authentication message, including files info
|
client = FileStorage::Client.new token, service_name
|
||||||
#
|
client.login
|
||||||
|
|
||||||
token = FileStorage::Token.new 1002, "karchnu"
|
files.each do |file|
|
||||||
authentication_message = FileStorage::Authentication.new token, upload_requests
|
puts "upload: #{file}"
|
||||||
pp! authentication_message
|
pp! client.upload file
|
||||||
client.send FileStorage::MessageType::Authentication.to_u8, authentication_message.to_json
|
puts "transfer"
|
||||||
|
client.transfer file
|
||||||
#
|
|
||||||
# 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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
client.close
|
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
|
|
||||||
|
@ -1,64 +1,106 @@
|
|||||||
|
require "ipc"
|
||||||
|
|
||||||
class FileStorage::Client
|
class FileStorage::Client < IPC::Client
|
||||||
|
property auth_token : String
|
||||||
|
|
||||||
def login(token : String)
|
def initialize(@auth_token, service_name = "filestorage")
|
||||||
request = FileStorage::Request::Login.new token
|
super service_name
|
||||||
|
end
|
||||||
|
|
||||||
|
def login
|
||||||
|
request = FileStorage::Request::Login.new auth_token
|
||||||
send request
|
send request
|
||||||
|
|
||||||
response = parse_message [ FileStorage::Response::Login, FileStorage::Response::Error ], read
|
response = parse_message [
|
||||||
|
FileStorage::Response::Login,
|
||||||
|
FileStorage::Errors::GenericError
|
||||||
|
], read
|
||||||
|
|
||||||
case response
|
if response.responds_to? :mid
|
||||||
when FileStorage::Response::Login
|
if request.mid != response.mid
|
||||||
# Received favorites, likes, etc.
|
raise "mid from response != request"
|
||||||
when FileStorage::Response::Error
|
end
|
||||||
raise "user was not logged in: #{response.reason}"
|
else
|
||||||
|
raise "response doen't even have mid"
|
||||||
end
|
end
|
||||||
|
|
||||||
response
|
response
|
||||||
end
|
end
|
||||||
|
|
||||||
def transfer(file_info : FileInfo, count, bindata)
|
def get_file_info(file_path : String)
|
||||||
request = FileStorage::Request::PutChunk.new file_info, count, bindata
|
file_info : FileStorage::FileInfo
|
||||||
send request
|
file = File.open(file_path)
|
||||||
|
file_info = FileStorage::FileInfo.new file
|
||||||
response = parse_message [ FileStorage::Response::PutChunk, FileStorage::Response::Error ], read
|
file.close
|
||||||
|
file_info.not_nil!
|
||||||
case response
|
|
||||||
when FileStorage::Response::PutChunk
|
|
||||||
when FileStorage::Response::Error
|
|
||||||
raise "File chunk was not transfered: #{response.reason}"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
response
|
def transfer(file_path : String)
|
||||||
|
file_info = get_file_info file_path
|
||||||
|
|
||||||
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
def download(filedigest = nil, name = nil, tags = nil)
|
def download(filedigest = nil, name = nil, tags = nil)
|
||||||
request = FileStorage::Request::Download.new filedigest, name, tags
|
request = FileStorage::Request::Download.new filedigest, name, tags
|
||||||
send request
|
send request
|
||||||
|
|
||||||
response = parse_message [ FileStorage::Response::Download, FileStorage::Response::Error ], read
|
response = parse_message [
|
||||||
|
FileStorage::Response::Download,
|
||||||
case response
|
FileStorage::Errors::GenericError
|
||||||
when FileStorage::Response::Download
|
], read
|
||||||
when FileStorage::Response::Error
|
|
||||||
raise "Download request denied: #{response.reason}"
|
|
||||||
end
|
|
||||||
|
|
||||||
response
|
response
|
||||||
end
|
end
|
||||||
|
|
||||||
def upload(token : String)
|
def upload(file : String)
|
||||||
request = FileStorage::Request::Upload.new token
|
file_info : FileStorage::FileInfo
|
||||||
|
File.open(file) do |f|
|
||||||
|
file_info = FileStorage::FileInfo.new f
|
||||||
|
request = FileStorage::Request::Upload.new file_info
|
||||||
send request
|
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}"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
response = parse_message [
|
||||||
|
FileStorage::Response::Upload,
|
||||||
|
FileStorage::Errors::GenericError
|
||||||
|
], read
|
||||||
|
|
||||||
response
|
response
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -46,7 +46,7 @@ class FileStorage::Storage
|
|||||||
# - users/ : DODB UserData (for later use: quotas, rights)
|
# - users/ : DODB UserData (for later use: quotas, rights)
|
||||||
|
|
||||||
def initialize(@root)
|
def initialize(@root)
|
||||||
@db = DODB::DataBase(TransferInfo).new "'#{@root}/meta"
|
@db = DODB::DataBase(TransferInfo).new "#{@root}/meta"
|
||||||
|
|
||||||
# Where to store uploaded files.
|
# Where to store uploaded files.
|
||||||
FileUtils.mkdir_p "#{@root}/files"
|
FileUtils.mkdir_p "#{@root}/files"
|
||||||
|
@ -19,6 +19,8 @@ class FileStorage::FileInfo
|
|||||||
nb_chunks : Int32
|
nb_chunks : Int32
|
||||||
digest : String
|
digest : String
|
||||||
tags : Array(String)
|
tags : Array(String)
|
||||||
|
|
||||||
|
initialize(file : File, tags = nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
class TransferInfo
|
class TransferInfo
|
||||||
@ -35,7 +37,8 @@ class FileStorage::UserData
|
|||||||
property uploads : Array(Upload) # NOT USED.
|
property uploads : Array(Upload) # NOT USED.
|
||||||
property downloads : Array(Download) # 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
|
end
|
||||||
|
|
||||||
root/
|
root/
|
||||||
|
Loading…
Reference in New Issue
Block a user