Skip to content

Bind firmware downloads to active network interface#99

Merged
jasontwong merged 3 commits into
mainfrom
jwong-eng-1861
May 20, 2026
Merged

Bind firmware downloads to active network interface#99
jasontwong merged 3 commits into
mainfrom
jwong-eng-1861

Conversation

@jasontwong
Copy link
Copy Markdown
Contributor

Summary

  • Binary.Downloader was opening Mint connections with no interface binding, so the OS default route (often ppp0 at metric 0) was used for all downloads regardless of which interface NetworkMonitor had selected
  • When NetworkMonitor switched to a higher-priority interface (eth0), in-flight and retried download connections stayed on ppp0; if ppp0 then lost internet the download stalled
  • On each connect attempt (including retries), the downloader now queries NetworkMonitor for the currently bound interface and passes bind_to_device to Mint.HTTP.connect/4 — the same mechanism already used by Cloud.Socket

Fixes: https://linear.app/peridio/issue/ENG-1861

Test plan

  • Existing 256-test suite passes (mix test)
  • Two new unit tests in "interface binding" describe block:
    • returns empty transport opts when no interface is bound (default state)
    • returns [bind_to_device: "eth0"] when NetworkMonitor has a bound interface
  • On a multi-interface device (eth0 + ppp0 with disconnect_on_higher_priority), trigger a firmware update while on ppp0, then bring up eth0 — download should migrate to eth0 after the next retry rather than stalling when ppp0 drops

Binary.Downloader was opening Mint connections with no interface binding,
so downloads routed through the OS default (often ppp0 at metric 0) even
after NetworkMonitor switched to a higher-priority interface like eth0.
When ppp0 lost internet the download stalled; retries went back to ppp0.

On each connect attempt, ask NetworkMonitor for the current bound interface
and pass bind_to_device to Mint.HTTP.connect/4. Retries after an idle
timeout now bind to whichever interface is active at that moment.

Guards against NetworkMonitor not being started (test environment).
Two tests covering the bound_interface_transport_opts/0 logic:
- returns empty opts when NetworkMonitor has no bound interface (default
  test environment state)
- returns [bind_to_device: ifname] when an interface is bound, verified
  by temporarily updating NetworkMonitor state via :sys.replace_state
Copilot AI review requested due to automatic review settings May 19, 2026 00:24
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the firmware download path to bind each HTTP connection attempt to the currently selected active network interface (as determined by Peridiod.Cloud.NetworkMonitor), preventing downloads from sticking to the OS default route when the preferred interface changes.

Changes:

  • Passes transport_opts: [bind_to_device: ifname] into Mint.HTTP.connect/4 for each download (and retry) connect attempt based on NetworkMonitor’s bound interface.
  • Adds Downloader.bound_interface_transport_opts/0 helper to translate the currently bound interface into Mint transport options.
  • Adds unit tests covering the “no bound interface” and “bound interface present” transport opts cases.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
lib/peridiod/binary/downloader.ex Binds Mint HTTP connections to the currently bound network interface via bind_to_device.
test/peridiod/binary/downloader_test.exs Adds unit tests for the new interface-binding transport options helper.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/peridiod/binary/downloader.ex Outdated
Replace Process.whereis + GenServer.call with a try/catch :exit so the
downloader returns [] gracefully if NetworkMonitor dies or restarts
between the existence check and the call. Adds a test that kills the
process mid-flight to verify the exit-safety path.
@jasontwong jasontwong requested a review from lee-reinhardt May 19, 2026 00:38
@jasontwong jasontwong merged commit 9b7be64 into main May 20, 2026
3 checks passed
@jasontwong jasontwong deleted the jwong-eng-1861 branch May 20, 2026 13:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants