From 71949fd1a2fe826594a0c62b79d5ac8002911e3d Mon Sep 17 00:00:00 2001 From: Josh Kalderimis <josh.kalderimis@gmail.com> 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..bdb7477 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_network_and_time_check() + {: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(:check_network_and_time, socket) do + cond do + network_connected?(socket) && time_synchronized?(socket) -> {:noreply, socket, {:continue, :connect}} - _ -> - Logger.info("[NervesHubLink] waiting for network to become available") - schedule_network_availability_check(2_000) - {:noreply, socket} + !network_connected?(socket) && !time_synchronized?(socket) -> + network_check_with_message( + "[NervesHubLink] waiting for network to become available and time to sync", + socket + ) + + !network_connected?(socket) -> + network_check_with_message( + "[NervesHubLink] waiting for network to become available", + socket + ) + + !time_synchronized?(socket) -> + network_check_with_message("[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 network_check_with_message(msg, socket) do + Logger.info(msg) + schedule_network_and_time_check(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_network_and_time_check(delay \\ 100) do + Process.send_after(self(), :check_network_and_time, delay) end defp handle_join_reply(%{"firmware_url" => url} = update, socket) when is_binary(url) do