From 262a1dcc37b8d22fd00c11981c9da9411420e311 Mon Sep 17 00:00:00 2001 From: Josh Kalderimis Date: Fri, 24 May 2024 17:54:27 +1200 Subject: [PATCH] check time synchronization before socket connection --- lib/nerves_hub_link/configurator.ex | 10 +++-- lib/nerves_hub_link/socket.ex | 63 ++++++++++++++++++++++------- 2 files changed, 54 insertions(+), 19 deletions(-) diff --git a/lib/nerves_hub_link/configurator.ex b/lib/nerves_hub_link/configurator.ex index ee47000..fbfb493 100644 --- a/lib/nerves_hub_link/configurator.ex +++ b/lib/nerves_hub_link/configurator.ex @@ -9,7 +9,6 @@ defmodule NervesHubLink.Configurator do defmodule Config do defstruct archive_public_keys: [], connect: true, - connect_wait_for_network: true, data_path: "/data/nerves-hub", device_api_host: nil, device_api_port: 443, @@ -25,12 +24,13 @@ defmodule NervesHubLink.Configurator do request_fwup_public_keys: false, shared_secret: [], socket: [], - ssl: [] + ssl: [], + wait_for_network: true, + wait_for_time_sync: true @type t() :: %__MODULE__{ archive_public_keys: [binary()], connect: boolean(), - connect_wait_for_network: boolean(), data_path: Path.t(), device_api_host: String.t(), device_api_port: String.t(), @@ -46,7 +46,9 @@ defmodule NervesHubLink.Configurator do request_fwup_public_keys: boolean(), shared_secret: [product_key: String.t(), product_secret: String.t()], socket: any(), - ssl: [:ssl.tls_client_option()] + ssl: [:ssl.tls_client_option()], + wait_for_network: boolean(), + wait_for_time_sync: boolean() } end diff --git a/lib/nerves_hub_link/socket.ex b/lib/nerves_hub_link/socket.ex index 154a584..1429109 100644 --- a/lib/nerves_hub_link/socket.ex +++ b/lib/nerves_hub_link/socket.ex @@ -90,12 +90,8 @@ defmodule NervesHubLink.Socket do |> assign(connected_at: nil) |> assign(joined_at: nil) - if config.connect_wait_for_network do - schedule_network_availability_check() - {:ok, socket} - else - {:ok, socket, {:continue, :connect}} - end + schedule_preconnect_checks() + {:ok, socket} end @impl Slipstream @@ -388,15 +384,25 @@ defmodule NervesHubLink.Socket do end @impl Slipstream - def handle_info(:connect_check_network_availability, socket) do - case :inet.gethostbyname(to_charlist(socket.assigns.config.device_api_host)) do - {:ok, _} -> + def handle_info(:preconnect_checks, socket) do + network? = network_connected?(socket) + time? = time_synchronized?(socket) + + cond do + network? && time? -> {:noreply, socket, {:continue, :connect}} - _ -> - Logger.info("[NervesHubLink] waiting for network to become available") - schedule_network_availability_check(2_000) - {:noreply, socket} + !network? -> + log_and_reschedule_checks( + "[NervesHubLink] waiting for network to become available", + socket + ) + + !time? -> + log_and_reschedule_checks( + "[NervesHubLink] waiting for time to sync", + socket + ) end end @@ -447,6 +453,33 @@ defmodule NervesHubLink.Socket do {:noreply, socket} end + defp network_connected?(%{assigns: %{config: config}}) do + if config.wait_for_network do + host = to_charlist(config.device_api_host) + + case :inet.gethostbyname(host) do + {:ok, _} -> true + _ -> false + end + else + true + end + end + + defp time_synchronized?(%{assigns: %{config: config}}) do + if config.wait_for_time_sync do + NervesTime.synchronized?() + else + true + end + end + + defp log_and_reschedule_checks(msg, socket) do + Logger.info(msg) + schedule_preconnect_checks(2_000) + {:noreply, socket} + end + @impl Slipstream def handle_topic_close(topic, reason, socket) when reason != :left do if topic == @device_topic do @@ -485,8 +518,8 @@ defmodule NervesHubLink.Socket do disconnect(socket) end - defp schedule_network_availability_check(delay \\ 100) do - Process.send_after(self(), :connect_check_network_availability, delay) + defp schedule_preconnect_checks(delay \\ 100) do + Process.send_after(self(), :preconnect_checks, delay) end defp handle_join_reply(%{"firmware_url" => url} = update, socket) when is_binary(url) do