Show a dynamically updated list of NTS servers #1
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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))
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue