Show a dynamically updated list of NTS servers #1

Merged
mike merged 21 commits from liveview into main 2024-07-26 09:35:19 -04:00
5 changed files with 47 additions and 23 deletions
Showing only changes of commit 7b91ca2245 - Show all commits

View File

@ -25,12 +25,16 @@ defmodule Chronoscope.NTS do
|> Enum.map(fn {_, pid, _, _} -> @genserver.call(pid, :list) end) |> Enum.map(fn {_, pid, _, _} -> @genserver.call(pid, :list) end)
end end
def list_clients(clients) do def list_clients(servers) do
clients servers
|> Enum.map(&client_pid/1) |> Enum.map(&client_pid/1)
|> Enum.map(fn pid -> @genserver.call(pid, :list, @timeout_in_milliseconds) end) |> Enum.map(fn pid -> @genserver.call(pid, :list, @timeout_in_milliseconds) end)
end end
def start_client(server) do
client_pid(server)
end
def auto_refresh(server) do def auto_refresh(server) do
server server
|> client_pid() |> client_pid()

View File

@ -3,6 +3,7 @@ defmodule Chronoscope.NTS.Client do
alias Chronoscope.NTS alias Chronoscope.NTS
alias Chronoscope.NTS.KeyEstablishmentClient alias Chronoscope.NTS.KeyEstablishmentClient
alias ChronoscopeWeb.Endpoint
@interval_in_seconds 30 @interval_in_seconds 30
@timeout_in_milliseconds 10_000 @timeout_in_milliseconds 10_000
@ -17,13 +18,13 @@ defmodule Chronoscope.NTS.Client do
@impl true @impl true
def init(server) do def init(server) do
now = utc_now() Endpoint.broadcast(@topic, "initializing", server)
{:ok, {:ok,
%{ %{
server: server, server: server,
key_establishment_response: {:error, "initializing"}, key_establishment_response: {:error, "initializing"},
last_key_establishment: DateTime.add(now, -@interval_in_seconds, :second) last_key_establishment: DateTime.add(utc_now(), -@interval_in_seconds, :second)
}} }}
end end
@ -53,6 +54,8 @@ defmodule Chronoscope.NTS.Client do
@impl true @impl true
def handle_call(:cancel_auto_refresh, _from, %{timer: timer} = state) do def handle_call(:cancel_auto_refresh, _from, %{timer: timer} = state) do
:timer.cancel(timer) :timer.cancel(timer)
Endpoint.broadcast(@topic, "cancel-auto-refresh", state.server)
{:reply, :ok, Map.delete(state, :timer)} {:reply, :ok, Map.delete(state, :timer)}
end end
@ -79,7 +82,7 @@ defmodule Chronoscope.NTS.Client do
if interval_surpassed?(now, state.last_key_establishment) do if interval_surpassed?(now, state.last_key_establishment) do
state state
|> Map.merge(current_data(state, now)) |> Map.merge(current_data(state, now))
|> tap(&ChronoscopeWeb.Endpoint.broadcast(@topic, "key-exchange", Map.delete(&1, :timer))) |> tap(&Endpoint.broadcast(@topic, "key-exchange", Map.delete(&1, :timer)))
else else
state state
end end

View File

@ -5,9 +5,9 @@ defmodule ChronoscopeWeb.ClientActivator do
alias Chronoscope.NTS alias Chronoscope.NTS
alias Chronoscope.NTS.Parse alias Chronoscope.NTS.Parse
alias ChronoscopeWeb.Endpoint
@activate_interval_in_milliseconds 300_000 @topic Application.compile_env(:chronoscope, :nts_topic)
@nts_file Application.compile_env(:chronoscope, :nts_file) @nts_file Application.compile_env(:chronoscope, :nts_file)
def start_link(_) do def start_link(_) do
@ -16,29 +16,33 @@ defmodule ChronoscopeWeb.ClientActivator do
@impl true @impl true
def init(_) do def init(_) do
nts_servers = Endpoint.subscribe(@topic)
nts_servers()
|> tap(fn servers -> Enum.each(servers, &NTS.auto_refresh/1) end)
:timer.send_interval(@activate_interval_in_milliseconds, :ensure_activated) {:ok, %{nts_servers: nts_servers() |> tap(&start_clients/1)}}
{:ok, %{nts_servers: nts_servers}}
end end
@impl true @impl true
def handle_info(:ensure_activated, state) do def handle_info(%{topic: @topic, event: "initializing", payload: server}, state) do
Enum.each(state.nts_servers, &NTS.auto_refresh/1) if server in state.nts_servers do
Logger.info("activating #{inspect(server)}")
NTS.auto_refresh(server)
end
{:noreply, state} {:noreply, state}
end end
@impl true @impl true
def handle_info(:activate_clients, _state) do def handle_info(%{topic: @topic, event: "cancel-auto-refresh", payload: server}, state) do
nts_servers = if server in state.nts_servers do
nts_servers() Logger.info("#{inspect(server)} was deactivated")
|> tap(fn servers -> Enum.each(servers, &NTS.auto_refresh/1) end) end
{:noreply, %{nts_servers: nts_servers}} {:noreply, state}
end
@impl true
def handle_info(_, state) do
{:noreply, state}
end end
@impl true @impl true
@ -46,6 +50,10 @@ defmodule ChronoscopeWeb.ClientActivator do
{:reply, state.nts_servers, state} {:reply, state.nts_servers, state}
end end
defp start_clients(servers) do
Enum.each(servers, &NTS.start_client/1)
end
defp nts_servers() do defp nts_servers() do
File.touch(Application.app_dir(:chronoscope, @nts_file)) File.touch(Application.app_dir(:chronoscope, @nts_file))

View File

@ -4,14 +4,17 @@ defmodule ChronoscopeWeb.IndexLive do
alias Chronoscope.NTS alias Chronoscope.NTS
alias Chronoscope.NTS.KeyEstablishmentResponse alias Chronoscope.NTS.KeyEstablishmentResponse
alias ChronoscopeWeb.ClientActivator alias ChronoscopeWeb.ClientActivator
alias ChronoscopeWeb.Endpoint
@topic Application.compile_env(:chronoscope, :nts_topic) @topic Application.compile_env(:chronoscope, :nts_topic)
@impl true
def mount(_params, _session, socket) do def mount(_params, _session, socket) do
ChronoscopeWeb.Endpoint.subscribe(@topic) Endpoint.subscribe(@topic)
{:ok, assign(socket, %{servers: server_list(), clients: client_list()})} {:ok, assign(socket, %{servers: server_list(), clients: client_list()})}
end end
@impl true
def handle_info(%{topic: @topic, event: "key-exchange", payload: client}, socket) do def handle_info(%{topic: @topic, event: "key-exchange", payload: client}, socket) do
if client.server in socket.assigns.servers do if client.server in socket.assigns.servers do
{:noreply, update(socket, :clients, &update_client(&1, client))} {:noreply, update(socket, :clients, &update_client(&1, client))}
@ -20,6 +23,11 @@ defmodule ChronoscopeWeb.IndexLive do
end end
end end
@impl true
def handle_info(_, socket) do
{:noreply, socket}
end
defp update_client(client_list, client) do defp update_client(client_list, client) do
Enum.map(client_list, &if(client.server == &1.server, do: client, else: &1)) Enum.map(client_list, &if(client.server == &1.server, do: client, else: &1))
end end
@ -29,7 +37,6 @@ defmodule ChronoscopeWeb.IndexLive do
end end
defp client_list() do defp client_list() do
server_list() server_list() |> NTS.list_clients()
|> NTS.list_clients()
end end
end end

View File

@ -5,3 +5,5 @@ paris.time.system76.com
oregon.time.system76.com oregon.time.system76.com
ohio.time.system76.com ohio.time.system76.com
brazil.time.system76.com brazil.time.system76.com
time.cloudflare.com
nts.netnod.se