160 lines
4.1 KiB
Crystal
160 lines
4.1 KiB
Crystal
|
|
require "dodb"
|
|
require "base64"
|
|
|
|
require "../common/utils"
|
|
|
|
# XXX TODO FIXME: architectural questions
|
|
# wonder why I should keep the user upload and download requests
|
|
# the server can be just for uploads, delegating downloads to HTTP
|
|
|
|
|
|
# reception of a file chunk
|
|
def hdl_transfer(message : FileStorage::Transfer, user : User) : FileStorage::Response
|
|
|
|
# We received a message containing a chunk of file.
|
|
|
|
mid = message.mid
|
|
mid ||= "no message id"
|
|
|
|
# Get the transfer info from the db
|
|
transfer_info = Context.db_by_filedigest.get message.filedigest
|
|
|
|
# TODO: if we don't have the information
|
|
if transfer_info.nil?
|
|
# TODO
|
|
end
|
|
|
|
# TODO: verify that the chunk sent was really missing
|
|
chunk_number = message.chunk.n - 1
|
|
|
|
# TODO: verify the digest
|
|
|
|
data = Base64.decode message.data
|
|
write_a_chunk user.uid.to_s, transfer_info.file_info, chunk_number, data
|
|
|
|
# TODO: register the file with dodb, with its tags
|
|
|
|
remove_chunk_from_db transfer_info, message.chunk.n
|
|
|
|
FileStorage::Response.new mid, "Ok"
|
|
|
|
rescue e
|
|
puts "Error handling transfer: #{e.message}"
|
|
FileStorage::Response.new mid.not_nil!, "Not Ok", "Unexpected error: #{e.message}"
|
|
end
|
|
|
|
# TODO
|
|
# the client sent an upload request
|
|
def hdl_upload(request : FileStorage::UploadRequest,
|
|
user : User,
|
|
event : IPC::Event::Message) : FileStorage::Response
|
|
|
|
puts "hdl upload: mid=#{request.mid}"
|
|
pp! request
|
|
|
|
FileStorage::Response.new request.mid, "Upload OK"
|
|
end
|
|
|
|
# TODO
|
|
# the client sent a download request
|
|
def hdl_download(request : FileStorage::DownloadRequest,
|
|
user : User,
|
|
event : IPC::Event::Message) : FileStorage::Response
|
|
|
|
puts "hdl download: mid=#{request.mid}"
|
|
pp! request
|
|
|
|
FileStorage::Response.new request.mid, "Download OK"
|
|
end
|
|
|
|
|
|
# Entry point for request management
|
|
# Each request should have a response.
|
|
# Then, responses are sent in a single message.
|
|
def hdl_requests(requests : Array(FileStorage::Request),
|
|
user : User,
|
|
event : IPC::Event::Message) : Array(FileStorage::Response)
|
|
|
|
puts "hdl request"
|
|
responses = Array(FileStorage::Response).new
|
|
|
|
requests.each do |request|
|
|
case request
|
|
when FileStorage::DownloadRequest
|
|
responses << hdl_download request, user, event
|
|
when FileStorage::UploadRequest
|
|
responses << hdl_upload request, user, event
|
|
else
|
|
raise "request not understood"
|
|
end
|
|
|
|
puts
|
|
end
|
|
|
|
responses
|
|
end
|
|
|
|
# store the client in connected_users and users_status
|
|
# if already in users_status:
|
|
# check if the requests are the same
|
|
# if not: add them to the user structure in users_status
|
|
def hdl_authentication(event : IPC::Event::Message)
|
|
|
|
authentication_message =
|
|
FileStorage::Authentication.from_json(
|
|
String.new event.message.payload
|
|
)
|
|
|
|
userid = authentication_message.token.uid
|
|
|
|
puts "user authentication: #{userid}"
|
|
|
|
# Is the user already recorded in users_status?
|
|
if Context.users_status[userid]?
|
|
puts "We already knew this user"
|
|
|
|
Context.connected_users[event.connection.fd] = userid
|
|
# TODO
|
|
pp! Context.connected_users
|
|
pp! Context.users_status[userid]
|
|
else
|
|
# AuthenticationMessage includes requests.
|
|
new_user =
|
|
User.new authentication_message.token,
|
|
authentication_message.uploads,
|
|
authentication_message.downloads
|
|
|
|
Context.connected_users[event.connection.fd] = userid
|
|
|
|
# record the new user in users_status
|
|
Context.users_status[userid] = new_user
|
|
|
|
puts "New user is: #{new_user.token.login}"
|
|
end
|
|
|
|
# The user is now connected.
|
|
user = Context.users_status[userid]
|
|
|
|
# We verify the user's rights to upload files.
|
|
# TODO RIGHTS
|
|
# if user wants to upload but not allowed to: Response
|
|
# if user wants to get a file but not allowed to: Response
|
|
|
|
# The user is authorized to upload files.
|
|
|
|
# TODO: quotas
|
|
# Quotas are not defined yet.
|
|
|
|
responses = hdl_requests [ authentication_message.uploads, authentication_message.downloads ].flatten,
|
|
Context.users_status[userid],
|
|
event
|
|
|
|
# Sending a response, containing a response for each request.
|
|
# The response is "Ok" when the message is well received and authorized.
|
|
response = FileStorage::Responses.new authentication_message.mid, "Ok", responses
|
|
event.connection.send FileStorage::MessageType::Responses.to_u8, response.to_json
|
|
pp! FileStorage::MessageType::Responses.to_u8
|
|
pp! response
|
|
end
|