71 lines
1.6 KiB
Elixir
71 lines
1.6 KiB
Elixir
defmodule Frajtano.Agent do
|
|
alias Frajtano.Peer
|
|
use GenServer
|
|
|
|
def start_link(args) do
|
|
GenServer.start_link(__MODULE__, nil, [{:name, __MODULE__} | args])
|
|
end
|
|
|
|
@impl true
|
|
def init(_) do
|
|
{:ok,
|
|
%{
|
|
keys: %{}
|
|
}}
|
|
end
|
|
|
|
@impl true
|
|
def handle_call({:identities}, _from, state) do
|
|
idents =
|
|
for(
|
|
{_, peer, :worker, _} <- DynamicSupervisor.which_children(Frajtano.Peer),
|
|
is_pid(peer),
|
|
do: peer
|
|
)
|
|
|> Task.async_stream(fn peer ->
|
|
with {:ok, idents} <- Peer.identities(peer),
|
|
do: {:ok, {idents, peer}}
|
|
end)
|
|
|
|
|
|
# Double :ok-wrapping because of Task.async_stream
|
|
idents = (for {:ok, {:ok, {idents, peer}}} <- idents, do: {idents, peer})
|
|
|
|
{
|
|
:reply,
|
|
{:ok, for({idents, _} <- idents, ident <- idents, do: ident)},
|
|
%{
|
|
state
|
|
| keys:
|
|
for({idents, peer} <- idents, {key, _comment} <- idents, into: %{}, do: {key, peer})
|
|
}
|
|
}
|
|
end
|
|
|
|
@impl true
|
|
def handle_call({:sign, {key, _, _} = req}, _from, state) do
|
|
{:reply, Peer.sign(state.keys[key], req), state}
|
|
end
|
|
|
|
@impl true
|
|
def handle_call({:add_peer, path}, _from, state) do
|
|
# TODO: deduplicate peers by socket path
|
|
case Peer.start(path) do
|
|
{:ok, _} -> {:reply, :ok, state}
|
|
{:error, error} -> {:reply, {:error, error}, state}
|
|
end
|
|
end
|
|
|
|
def identities(agent \\ __MODULE__) do
|
|
GenServer.call(agent, {:identities})
|
|
end
|
|
|
|
def sign(agent \\ __MODULE__, request) do
|
|
GenServer.call(agent, {:sign, request})
|
|
end
|
|
|
|
def add_peer(agent \\ __MODULE__, path) do
|
|
GenServer.call(agent, {:add_peer, path})
|
|
end
|
|
end
|