Skip to content
This repository has been archived by the owner on Jun 11, 2023. It is now read-only.

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
renatomassaro committed Oct 14, 2017
1 parent 05fbd36 commit 860ba62
Show file tree
Hide file tree
Showing 13 changed files with 291 additions and 51 deletions.
7 changes: 7 additions & 0 deletions lib/henforcer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -315,4 +315,11 @@ defmodule Helix.Henforcer do
end
end
end

defmacro get_and_drop(relay, value) do
quote do
value = Map.get(unquote(relay), unquote(value))
{value, Map.delete(unquote(relay), unquote(value))}
end
end
end
57 changes: 43 additions & 14 deletions lib/server/websocket/channel/server.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,26 @@ channel Helix.Server.Websocket.Channel.Server do

alias Helix.Server.State.Websocket.Channel, as: ServerWebsocketChannelState

alias Helix.Network.Websocket.Requests.Browse, as: BrowseRequest
alias Helix.Network.Websocket.Requests.Browse,
as: BrowseRequest

alias Helix.Software.Websocket.Requests.Cracker.Bruteforce,
as: CrackerBruteforceRequest
alias Helix.Software.Websocket.Requests.File.Download, as: FileDownloadRequest
alias Helix.Software.Websocket.Requests.PFTP.File.Add, as: PFTPFileAddRequest
alias Helix.Software.Websocket.Requests.File.Download,
as: FileDownloadRequest
alias Helix.Software.Websocket.Requests.PFTP.File.Add,
as: PFTPFileAddRequest
alias Helix.Software.Websocket.Requests.PFTP.File.Download,
as: PFTPFileDownloadRequest
alias Helix.Software.Websocket.Requests.PFTP.File.Remove,
as: PFTPFileRemoveRequest
alias Helix.Software.Websocket.Requests.PFTP.Server.Disable,
as: PFTPServerDisableRequest
alias Helix.Software.Websocket.Requests.PFTP.Server.Enable,
as: PFTPServerEnableRequest

alias Helix.Server.Websocket.Channel.Server.Join, as: ServerJoin
alias Helix.Server.Websocket.Channel.Server.Join,
as: ServerJoin
alias Helix.Server.Websocket.Channel.Server.Requests.Bootstrap,
as: BootstrapRequest

Expand Down Expand Up @@ -114,11 +120,43 @@ channel Helix.Server.Websocket.Channel.Server do
Params:
- *file_id: Which file to add to the player's PFTP.
Errors:
- "pftp_must_be_local": PFTP operations must happen at the local socket.
- Henforcer errors
"""
topic "pftp.file.add", PFTPFileAddRequest

@doc """
Removes a file from the player's PublicFTP.
Params:
- *file_id: Which file should be removed from the player's PFTP.
Errors:
- "pftp_must_be_local": PFTP operations must happen at the local socket.
- Henforcer errors
"""
topic "pftp.file.remove", PFTPFileRemoveRequest

@doc """
Downloads a file from a PublicFTP server.
# TODO: server param must be nip, not id.
Params:
- *server_id: The server from which the file is being downloaded.
- *file_id: ID of the file being downloaded.
- storage_id: Specify which storage the file should be downloaded to. Defaults
to the main storage.
Returns: RenderedProcess.t
Errors:
- "pftp_must_be_local": PFTP operations must happen at the local socket.
- Henforcer errors
"""
topic "pftp.file.download", PFTPFileDownloadRequest

@doc """
Browses to the specified address, which may be an IPv4 or domain name.
Expand Down Expand Up @@ -154,16 +192,7 @@ channel Helix.Server.Websocket.Channel.Server do
Note that all bruteforce attacks must originate from a server owned by the
entity starting the attack.
Returns:
%{
process_id: Process.id,
type: Process.type,
network_id: Network.id,
file_id: File.id | nil,
connection_id: Connection.id | nil,
source_ip: IPv4.t,
target_ip: IPv4.t
}
Returns: RenderedProcess.t
Errors:
- "cracker_not_found" - Player attempting the attack does not have a valid
Expand Down
2 changes: 1 addition & 1 deletion lib/software/henforcer/file.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ defmodule Helix.Software.Henforcer.File do
end
end

@type belongs_to_server_relay :: file_exists_relay
@type belongs_to_server_relay :: %{file: File.t, server: Server.t}
@type belongs_to_server_relay_partial :: file_exists_relay
@type belongs_to_server_error ::
{false, {:file, :not_belongs}, belongs_to_server_relay_partial}
Expand Down
2 changes: 1 addition & 1 deletion lib/software/henforcer/file/public_ftp.ex
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ defmodule Helix.Software.Henforcer.File.PublicFTP do
`server` (if any).
If there are no running PublicFTP servers, or if it's disabled, then this
henforce must return `false`.
henforce will return `false`.
"""
def file_exists?(server, file_id = %File.ID{}) do
henforce(FileHenforcer.file_exists?(file_id)) do
Expand Down
44 changes: 38 additions & 6 deletions lib/software/henforcer/file/transfer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,54 @@ defmodule Helix.Software.Henforcer.File.Transfer do
+ indirect checks along the way
"""
def can_transfer?(type, gateway_id, endpoint_id, storage_id, file_id) do
# Within the transfer context, `origin` is the server which owns the file,
# and `target` is the server which the file is being transferred to.
# However, outside this context, the caller only works with `gateway` and
# `destination`, which depending on the transfer type (download/upload) can
# act as both `origin` and `target`. Hence we need to "map in", from
# gateway/destination to origin/target and, once we are returning to the
# caller we have to "map out", returning the contextless gateway/destination

# "Maps in", from gateway/destination to origin/target.
{origin_id, target_id} =
if type == :download do
{endpoint_id, gateway_id}
else
{gateway_id, endpoint_id}
end

# "Maps out", from origin/target to gateway/destination.
assign_to_servers = fn origin, target ->
{gateway, destination} =
if type == :download do
{target, origin}
else
{origin, target}
end

%{gateway: gateway, destination: destination}
end

with \
true <- gateway_id != endpoint_id || :self_target,
{true, %{file: file}} <-
FileHenforcer.belongs_to_server?(file_id, origin_id),
{true, %{storage: storage}} <-
StorageHenforcer.belongs_to_server?(storage_id, target_id),
{true, _} <- StorageHenforcer.has_enough_space?(storage, file)
# /\ A transfer must be between different servers

# The file being downloaded belongs to the transfer's origin server
{true, r1} <- FileHenforcer.belongs_to_server?(file_id, origin_id),
file = r1.file,
{origin, r1} = get_and_drop(r1, :server),

# The destination storage belongs to the server
{true, r2} <- StorageHenforcer.belongs_to_server?(storage_id, target_id),
storage = r2.storage,
{target, r2} = get_and_drop(r2, :server),

# The destination storage has enough room for the file
{true, r3} <- StorageHenforcer.has_enough_space?(storage, file)
do
{true, relay(%{storage: storage, file: file})}
r = assign_to_servers.(origin, target)

{true, relay([r1, r2, r3, r])}
else
:self_target ->
{false, {:target, :self}, %{}}
Expand Down
7 changes: 3 additions & 4 deletions lib/software/henforcer/storage.ex
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,15 @@ defmodule Helix.Software.Henforcer.Storage do
end

def belongs_to_server?(storage = %Storage{}, server = %Server{}) do
relay = %{server: server, storage: storage}

with \
{:ok, owner_id} <- CacheQuery.from_storage_get_server(storage),
true <- owner_id == server.server_id || :not_belongs
do
reply_ok(relay)
reply_ok()
else
_ ->
reply_error({:storage, :not_belongs}, relay)
reply_error({:storage, :not_belongs})
end
|> wrap_relay(%{server: server, storage: storage})
end
end
34 changes: 34 additions & 0 deletions lib/software/public/pftp.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@ defmodule Helix.Software.Public.PFTP do
Public layer of the PublicFTP feature -- shortened to PFTP to avoid confusion.
"""

alias Helix.Network.Query.Network, as: NetworkQuery
alias Helix.Server.Model.Server
alias Helix.Software.Action.Flow.File.Transfer, as: FileTransferFlow
alias Helix.Software.Action.Flow.PublicFTP, as: PublicFTPFlow
alias Helix.Software.Model.File
alias Helix.Software.Model.PublicFTP
alias Helix.Software.Model.Storage

@internet_id NetworkQuery.internet().network_id

@spec enable_server(Server.t) ::
{:ok, PublicFTP.t}
Expand All @@ -31,4 +36,33 @@ defmodule Helix.Software.Public.PFTP do
| {:error, :internal}
def remove_file(pftp = %PublicFTP{}, pftp_file = %PublicFTP.File{}),
do: PublicFTPFlow.remove_file(pftp, pftp_file)

def download(
gateway_id = %Server.ID{},
pftp_file = %PublicFTP.File{},
storage = %Storage{},
file = %File{})
do
# PFTP downloads are "public", so must always happen over the internet.
network_id = @internet_id

network_info =
%{
gateway_id: gateway_id,
destination_id: pftp_file.server_id,
network_id: network_id,
bounces: [] # TODO 256
}

transfer =
FileTransferFlow.transfer(:pftp_download, file, storage, network_info)

case transfer do
{:ok, process} ->
{:ok, process}

{:error, _} ->
{:error, :internal}
end
end
end
13 changes: 13 additions & 0 deletions lib/software/query/storage.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
defmodule Helix.Software.Query.Storage do

alias Helix.Cache.Query.Cache, as: CacheQuery
alias Helix.Hardware.Model.Component
alias Helix.Server.Model.Server
alias Helix.Software.Model.File
alias Helix.Software.Model.Storage
alias Helix.Software.Internal.File, as: FileInternal
Expand Down Expand Up @@ -45,4 +47,15 @@ defmodule Helix.Software.Query.Storage do
[Component.id]
defdelegate get_storage_drives(storage),
to: StorageDriveInternal

# TODO Test
@spec get_main_storage(Server.idt) ::
Storage.id
def get_main_storage(server = %Server{}),
do: get_main_storage(server.server_id)
def get_main_storage(server_id = %Server.ID{}) do
server_id
|> CacheQuery.from_server_get_storages!()
|> List.first()
end
end
13 changes: 2 additions & 11 deletions lib/software/websocket/requests/file/download.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ request Helix.Software.Websocket.Requests.File.Download do

import HELL.Macros

alias Helix.Cache.Query.Cache, as: CacheQuery
alias Helix.Server.Model.Server
alias Helix.Software.Model.File
alias Helix.Software.Model.Storage
alias Helix.Software.Henforcer.File.Transfer, as: FileTransferHenforcer
alias Helix.Software.Public.File, as: FilePublic
alias Helix.Software.Query.Storage, as: StorageQuery

# Hack for elixir-lang issue #6577
@dialyzer {:nowarn_function, get_error: 1}
Expand All @@ -20,7 +20,7 @@ request Helix.Software.Websocket.Requests.File.Download do
if Map.has_key?(request.unsafe, "storage_id") do
request.unsafe["storage_id"]
else
get_download_storage(socket.assigns.gateway.server_id)
StorageQuery.get_main_storage(socket.assigns.gateway.server_id)
end

with \
Expand Down Expand Up @@ -95,15 +95,6 @@ request Helix.Software.Websocket.Requests.File.Download do

render_process()

@spec get_download_storage(Server.id) ::
Storage.id
defp get_download_storage(gateway_id) do
gateway_id
|> CacheQuery.from_server_get_storages()
|> elem(1)
|> List.first()
end

@spec get_error(reason :: {term, term} | term) ::
String.t
docp """
Expand Down
Loading

0 comments on commit 860ba62

Please sign in to comment.