From e6a567090d5e14605e6d4722fc51d7c56b9410ee Mon Sep 17 00:00:00 2001 From: Melonai Date: Fri, 4 Jun 2021 19:21:22 +0200 Subject: Transfer server API --- assets/src/network/channel/messages/messages.ts | 27 ++++++-- lib/rook/request.ex | 77 ---------------------- lib/rook/request/actions.ex | 25 +++++++ lib/rook/request/events.ex | 25 +++++++ lib/rook/request/request.ex | 83 ++++++++++++++++++++++++ lib/rook/share.ex | 79 ----------------------- lib/rook/share/actions.ex | 25 +++++++ lib/rook/share/events.ex | 25 +++++++ lib/rook/share/share.ex | 86 +++++++++++++++++++++++++ lib/rook_web/channels/request_channel.ex | 12 +++- lib/rook_web/channels/share_channel.ex | 18 ++++-- lib/rook_web/channels/token_channel.ex | 2 +- 12 files changed, 317 insertions(+), 167 deletions(-) delete mode 100644 lib/rook/request.ex create mode 100644 lib/rook/request/actions.ex create mode 100644 lib/rook/request/events.ex create mode 100644 lib/rook/request/request.ex delete mode 100644 lib/rook/share.ex create mode 100644 lib/rook/share/actions.ex create mode 100644 lib/rook/share/events.ex create mode 100644 lib/rook/share/share.ex diff --git a/assets/src/network/channel/messages/messages.ts b/assets/src/network/channel/messages/messages.ts index 6d43a37..3f2253d 100644 --- a/assets/src/network/channel/messages/messages.ts +++ b/assets/src/network/channel/messages/messages.ts @@ -5,7 +5,8 @@ export type AnyMessage = ShareMessage | RequestMessage; export type ShareMessage = | NewRequestMessage | RequestCancelledMessage - | AcceptShareMessage; + | ShareAcceptedMessage + | RequestIceCandidateMessage; export type NewRequestMessage = { token: string; @@ -15,16 +16,34 @@ export type RequestCancelledMessage = { token: string; }; -export type AcceptShareMessage = { +export type ShareAcceptedMessage = { token: string; sdp: string; - type: string; + type: RTCSdpType; +}; + +export type RequestIceCandidateMessage = { + token: string; + candidate: RTCIceCandidateInit; }; // Messages for the requestor -export type RequestMessage = RequestAcknowledgedMessage | ShareCancelledMessage; +export type RequestMessage = + | RequestAcknowledgedMessage + | RequestAcceptedMessage + | ShareCancelledMessage + | ShareIceCandidateMessage; export type RequestAcknowledgedMessage = {}; +export type RequestAcceptedMessage = { + sdp: string; + type: RTCSdpType; +}; + export type ShareCancelledMessage = {}; + +export type ShareIceCandidateMessage = { + candidate: RTCIceCandidateInit; +}; diff --git a/lib/rook/request.ex b/lib/rook/request.ex deleted file mode 100644 index b795c5c..0000000 --- a/lib/rook/request.ex +++ /dev/null @@ -1,77 +0,0 @@ -defmodule Rook.Request do - use GenServer - - defmodule State do - @type t :: %__MODULE__{ - token: String.t(), - share_token: String.t(), - channel_pid: pid() - } - - defstruct [:token, :share_token, :channel_pid] - end - - ## Client - - def init([token, share_token, channel_pid]) do - Process.flag(:trap_exit, true) - Process.link(channel_pid) - Rook.Share.new_request(share_token, token) - {:ok, %State{token: token, share_token: share_token, channel_pid: channel_pid}} - end - - def start(token, share_token) do - GenServer.start(__MODULE__, [token, share_token, self()], name: via(token)) - end - - def acknowledge_request(token) do - cast(token, {:request_acknowledged}) - end - - def close(request_token, share_token) do - Rook.Share.request_cancelled(share_token, request_token) - end - - def close(request_token) do - cast(request_token, {:share_cancelled}) - end - - def get(token) do - case Registry.lookup(Registry.Request, token) do - [{pid, _}] -> pid - _ -> nil - end - end - - def exists?(token) do - get(token) != nil - end - - ## Server - - def handle_cast({:request_acknowledged}, state) do - notify(state.token, "request_acknowledged", %{}) - {:noreply, state} - end - - def handle_cast({:share_cancelled}, state) do - notify(state.token, "share_cancelled", %{}) - {:stop, :shutdown, state} - end - - def handle_info({:EXIT, pid, reason}, state) do - if state.channel_pid == pid do - Rook.Request.close(state.token, state.share_token) - end - - {:stop, reason, state} - end - - ## Helpers - - defp via(name), do: {:via, Registry, {Registry.Request, name}} - defp cast(token, params), do: GenServer.cast(via(token), params) - - defp notify(token, event, params), - do: RookWeb.Endpoint.broadcast!("request:" <> token, event, params) -end diff --git a/lib/rook/request/actions.ex b/lib/rook/request/actions.ex new file mode 100644 index 0000000..7c6a5d8 --- /dev/null +++ b/lib/rook/request/actions.ex @@ -0,0 +1,25 @@ +defmodule Rook.Request.Actions do + @moduledoc """ + Defines any actions a request is able to perform. + Should only be called from other Request modules. + """ + + def start(token, share_token) do + GenServer.start(Rook.Request, [token, share_token, self()], name: via(token)) + end + + def accept_share(token, description) do + cast(token, {:accept_share, description}) + end + + def ice_candidate(token, candidate) do + cast(token, {:ice_candidate, candidate}) + end + + def close(request_token, share_token) do + Rook.Share.Events.request_cancelled(share_token, request_token) + end + + defp via(name), do: {:via, Registry, {Registry.Request, name}} + defp cast(token, params), do: GenServer.cast(via(token), params) +end diff --git a/lib/rook/request/events.ex b/lib/rook/request/events.ex new file mode 100644 index 0000000..f5f6730 --- /dev/null +++ b/lib/rook/request/events.ex @@ -0,0 +1,25 @@ +defmodule Rook.Request.Events do + @moduledoc """ + Defines any outside events which can happen during a request's lifetime. + Usually called by Share modules. + """ + + def request_acknowledged(token) do + cast(token, {:request_acknowledged}) + end + + def request_accepted(token, description) do + cast(token, {:request_accepted, description}) + end + + def share_ice_candidate(token, candidate) do + cast(token, {:share_ice_candidate, candidate}) + end + + def share_cancelled(request_token) do + cast(request_token, {:share_cancelled}) + end + + defp via(name), do: {:via, Registry, {Registry.Request, name}} + defp cast(token, params), do: GenServer.cast(via(token), params) +end diff --git a/lib/rook/request/request.ex b/lib/rook/request/request.ex new file mode 100644 index 0000000..d0ee7c6 --- /dev/null +++ b/lib/rook/request/request.ex @@ -0,0 +1,83 @@ +defmodule Rook.Request do + @moduledoc """ + Auxiliary process which keeps any neccessary state of any RookWeb.RequestChannel process. + It can be accessed either through Rook.Request.Actions or Rook.Request.Events. + """ + + use GenServer + + defmodule State do + @type t :: %__MODULE__{ + token: String.t(), + share_token: String.t(), + channel_pid: pid() + } + + defstruct [:token, :share_token, :channel_pid] + end + + ## Client + + def get(token) do + case Registry.lookup(Registry.Request, token) do + [{pid, _}] -> pid + _ -> nil + end + end + + def exists?(token) do + get(token) != nil + end + + ## Server + + def init([token, share_token, channel_pid]) do + Process.flag(:trap_exit, true) + Process.link(channel_pid) + Rook.Share.Events.new_request(share_token, token) + {:ok, %State{token: token, share_token: share_token, channel_pid: channel_pid}} + end + + def handle_cast({:request_acknowledged}, state) do + notify(state.token, "request_acknowledged", %{}) + {:noreply, state} + end + + def handle_cast({:request_accepted, description}, state) do + notify(state.token, "request_accepted", description) + {:noreply, state} + end + + def handle_cast({:accept_share, description}, state) do + Rook.Share.Events.share_accepted(state.share_token, state.token, description) + {:noreply, state} + end + + def handle_cast({:ice_candidate, candidate}, state) do + Rook.Share.Events.request_ice_candidate(state.share_token, state.token, candidate) + {:noreply, state} + end + + def handle_cast({:share_ice_candidate, candidate}, state) do + notify(state.token, "ice_candidate", %{candidate: candidate}) + {:noreply, state} + end + + def handle_cast({:share_cancelled}, state) do + notify(state.token, "share_cancelled", %{}) + {:stop, :shutdown, state} + end + + def handle_info({:EXIT, pid, reason}, state) do + if state.channel_pid == pid do + Rook.Request.Actions.close(state.token, state.share_token) + end + + {:stop, reason, state} + end + + ## Helpers + + defp notify(token, event, params), + do: RookWeb.Endpoint.broadcast!("request:" <> token, event, params) +end diff --git a/lib/rook/share.ex b/lib/rook/share.ex deleted file mode 100644 index a1797ce..0000000 --- a/lib/rook/share.ex +++ /dev/null @@ -1,79 +0,0 @@ -defmodule Rook.Share do - use GenServer - - defmodule State do - @type t :: %__MODULE__{ - token: String.t(), - channel_pid: pid(), - requests: [String.t()] - } - - defstruct [:token, :channel_pid, requests: []] - end - - ## Client - - def init([token, channel_pid]) do - Process.flag(:trap_exit, true) - Process.link(channel_pid) - {:ok, %State{token: token, channel_pid: channel_pid}} - end - - def start(token) do - GenServer.start(__MODULE__, [token, self()], name: via(token)) - end - - def new_request(share_token, request_token) do - cast(share_token, {:new_request, request_token}) - end - - def request_cancelled(share_token, request_token) do - cast(share_token, {:request_cancelled, request_token}) - end - - def close(requests) do - Enum.each(requests, &Rook.Request.close/1) - end - - def get(token) do - case Registry.lookup(Registry.Share, token) do - [{pid, _}] -> pid - _ -> nil - end - end - - def exists?(token) do - get(token) != nil - end - - ## Server - - def handle_cast({:new_request, request_token}, state) do - # TODO: Check whether request exists. - %State{token: token, requests: requests} = state - notify(token, "new_request", %{token: request_token}) - {:noreply, %{state | requests: [request_token | requests]}} - end - - def handle_cast({:request_cancelled, request_token}, state) do - %State{token: token, requests: requests} = state - notify(token, "request_cancelled", %{request: request_token}) - {:noreply, %{state | requests: List.delete(requests, request_token)}} - end - - def handle_info({:EXIT, pid, reason}, state) do - if state.channel_pid == pid do - Rook.Share.close(state.requests) - end - - {:stop, reason, state} - end - - ## Helpers - - defp via(name), do: {:via, Registry, {Registry.Share, name}} - defp cast(token, params), do: GenServer.cast(via(token), params) - - defp notify(token, event, params), - do: RookWeb.Endpoint.broadcast!("share:" <> token, event, params) -end diff --git a/lib/rook/share/actions.ex b/lib/rook/share/actions.ex new file mode 100644 index 0000000..b8170fd --- /dev/null +++ b/lib/rook/share/actions.ex @@ -0,0 +1,25 @@ +defmodule Rook.Share.Actions do + @moduledoc """ + Defines any actions a share is able to perform. + Should only be called from other Share modules. + """ + + def start(token) do + GenServer.start(Rook.Share, [token, self()], name: via(token)) + end + + def accept_request(token, request_token, description) do + cast(token, {:accept_request, request_token, description}) + end + + def ice_candidate(token, request_token, candidate) do + cast(token, {:ice_candidate, request_token, candidate}) + end + + def close(requests) do + Enum.each(requests, &Rook.Request.Events.share_cancelled/1) + end + + defp via(name), do: {:via, Registry, {Registry.Share, name}} + defp cast(token, params), do: GenServer.cast(via(token), params) +end diff --git a/lib/rook/share/events.ex b/lib/rook/share/events.ex new file mode 100644 index 0000000..4ed8619 --- /dev/null +++ b/lib/rook/share/events.ex @@ -0,0 +1,25 @@ +defmodule Rook.Share.Events do + @moduledoc """ + Defines any outside events which can happen during a share's lifetime. + Usually called by Request modules. + """ + + def new_request(share_token, request_token) do + cast(share_token, {:new_request, request_token}) + end + + def share_accepted(share_token, request_token, description) do + cast(share_token, {:share_accepted, request_token, description}) + end + + def request_ice_candidate(token, request_token, candidate) do + cast(token, {:request_ice_candidate, request_token, candidate}) + end + + def request_cancelled(share_token, request_token) do + cast(share_token, {:request_cancelled, request_token}) + end + + defp via(name), do: {:via, Registry, {Registry.Share, name}} + defp cast(token, params), do: GenServer.cast(via(token), params) +end diff --git a/lib/rook/share/share.ex b/lib/rook/share/share.ex new file mode 100644 index 0000000..fe626c2 --- /dev/null +++ b/lib/rook/share/share.ex @@ -0,0 +1,86 @@ +defmodule Rook.Share do + @moduledoc """ + Auxiliary process which keeps any neccessary state of any RookWeb.ShareChannel process. + It can be accessed either through Rook.Share.Actions or Rook.Share.Events. + """ + + use GenServer + + defmodule State do + @type t :: %__MODULE__{ + token: String.t(), + channel_pid: pid(), + requests: [String.t()] + } + + defstruct [:token, :channel_pid, requests: []] + end + + ## Client + + def get(token) do + case Registry.lookup(Registry.Share, token) do + [{pid, _}] -> pid + _ -> nil + end + end + + def exists?(token) do + get(token) != nil + end + + ## Server + + def init([token, channel_pid]) do + Process.flag(:trap_exit, true) + Process.link(channel_pid) + {:ok, %State{token: token, channel_pid: channel_pid}} + end + + def handle_cast({:new_request, request_token}, state) do + # TODO: Check whether request exists. + %State{token: token, requests: requests} = state + notify(token, "new_request", %{token: request_token}) + {:noreply, %{state | requests: [request_token | requests]}} + end + + def handle_cast({:accept_request, request_token, description}, state) do + Rook.Request.Events.request_accepted(request_token, description) + {:noreply, state} + end + + def handle_cast({:share_accepted, request_token, description}, state) do + message = Map.put(description, :token, request_token) + notify(state.token, "share_accepted", message) + {:noreply, state} + end + + def handle_cast({:ice_candidate, request_token, candidate}, state) do + Rook.Request.Events.share_ice_candidate(request_token, candidate) + {:noreply, state} + end + + def handle_cast({:request_ice_candidate, request_token, candidate}, state) do + notify(state.token, "ice_candidate", %{token: request_token, candidate: candidate}) + {:noreply, state} + end + + def handle_cast({:request_cancelled, request_token}, state) do + %State{token: token, requests: requests} = state + notify(token, "request_cancelled", %{token: request_token}) + {:noreply, %{state | requests: List.delete(requests, request_token)}} + end + + def handle_info({:EXIT, pid, reason}, state) do + if state.channel_pid == pid do + Rook.Share.Actions.close(state.requests) + end + + {:stop, reason, state} + end + + ## Helpers + + defp notify(token, event, params), + do: RookWeb.Endpoint.broadcast!("share:" <> token, event, params) +end diff --git a/lib/rook_web/channels/request_channel.ex b/lib/rook_web/channels/request_channel.ex index 6290ae6..cc84b0f 100644 --- a/lib/rook_web/channels/request_channel.ex +++ b/lib/rook_web/channels/request_channel.ex @@ -4,7 +4,7 @@ defmodule RookWeb.RequestChannel do def join("request:" <> token, %{"share" => share_token}, socket) do if Rook.Token.match?(token, socket) do if Rook.Share.exists?(share_token) do - Rook.Request.start(token, share_token) + Rook.Request.Actions.start(token, share_token) {:ok, socket} else {:error, %{reason: "No such share exists."}} @@ -17,4 +17,14 @@ defmodule RookWeb.RequestChannel do def join("request:" <> _token, _params, _socket) do {:error, %{reason: "No share given to request."}} end + + def handle_in("accept_share", description, socket) do + Rook.Request.Actions.accept_share(socket.assigns.token, description) + {:noreply, socket} + end + + def handle_in("ice_candidate", %{"candidate" => candidate}, socket) do + Rook.Request.Actions.ice_candidate(socket.assigns.token, candidate) + {:noreply, socket} + end end diff --git a/lib/rook_web/channels/share_channel.ex b/lib/rook_web/channels/share_channel.ex index 0efb3ba..02c6fc0 100644 --- a/lib/rook_web/channels/share_channel.ex +++ b/lib/rook_web/channels/share_channel.ex @@ -5,15 +5,17 @@ defmodule RookWeb.ShareChannel do def join("share:" <> token, _params, socket) do if Rook.Token.match?(token, socket) do - Rook.Share.start(token) + Rook.Share.Actions.start(token) {:ok, socket} else {:error, %{reason: "Wrong token."}} end end - def handle_in("accept_request", %{"request" => _request_token}, socket) do - # TODO: Send request accept message. + def handle_in("accept_request", %{"token" => request_token} = params, socket) do + description = Map.delete(params, :token) + token = socket.assigns.token + Rook.Share.Actions.accept_request(token, request_token, description) {:noreply, socket} end @@ -21,8 +23,14 @@ defmodule RookWeb.ShareChannel do {:error, %{reason: "No request given to accept."}} end - def handle_out("new_request", %{request: request_token} = msg, socket) do - Rook.Request.acknowledge_request(request_token) + def handle_in("ice_candidate", %{"token" => request_token, "candidate" => candidate}, socket) do + token = socket.assigns.token + Rook.Share.Actions.ice_candidate(token, request_token, candidate) + {:noreply, socket} + end + + def handle_out("new_request", %{token: request_token} = msg, socket) do + Rook.Request.Events.request_acknowledged(request_token) push(socket, "new_request", msg) {:noreply, socket} end diff --git a/lib/rook_web/channels/token_channel.ex b/lib/rook_web/channels/token_channel.ex index 72cabb1..d91b6ac 100644 --- a/lib/rook_web/channels/token_channel.ex +++ b/lib/rook_web/channels/token_channel.ex @@ -6,6 +6,6 @@ defmodule RookWeb.TokenChannel do end def handle_in("get_token", _attrs, socket) do - {:reply, {:ok, %{token: socket.assigns[:token]}}, socket} + {:reply, {:ok, %{token: socket.assigns.token}}, socket} end end -- cgit 1.4.1