From f74df49d3369587eb3e1852e71af19653902591c Mon Sep 17 00:00:00 2001 From: Martino Ferrari Date: Mon, 2 Nov 2026 10:27:00 +0100 Subject: [PATCH] e1608: scan review fixes (EINTR in Scan::poll, cfg-based broadcast test, no per-tick copy) Co-Authored-By: Claude Opus 4.6 --- src/source/e1608/e1608_kind.cpp | 14 +++++++------- src/source/e1608/e1608_link.cpp | 5 ++++- src/source/e1608/e1608_source.cpp | 10 +++++----- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/source/e1608/e1608_kind.cpp b/src/source/e1608/e1608_kind.cpp index 5dc847b..9ba2d16 100644 --- a/src/source/e1608/e1608_kind.cpp +++ b/src/source/e1608/e1608_kind.cpp @@ -233,22 +233,22 @@ void hook_entry(GtkWidget* w, const FormPtr& f) { constexpr int kScanMs = 1500; ///< how long a scan listens constexpr int kTickMs = 50; ///< how often it drains the sockets -/// A result row's two ways to name the board, with the form they fill. +/// A result row's two ways to name the board: what each fills into the form (the other is cleared). struct Pick { FormPtr form; - std::string ip, mac; + std::string value; }; void free_pick(gpointer d, GClosure*) { delete static_cast(d); } void on_pick_address(AdwActionRow*, gpointer user) { Pick& p = *static_cast(user); - p.form->fill(p.ip, ""); + p.form->fill(p.value, ""); } void on_pick_mac(GtkButton*, gpointer user) { Pick& p = *static_cast(user); - p.form->fill("", p.mac); + p.form->fill("", p.value); } void add_result(const FormPtr& f, const DeviceInfo& d) { @@ -263,8 +263,8 @@ void add_result(const FormPtr& f, const DeviceInfo& d) { gtk_widget_set_valign(use_mac, GTK_ALIGN_CENTER); adw_action_row_add_suffix(ADW_ACTION_ROW(row), use_mac); g_signal_connect_data(row, "activated", G_CALLBACK(on_pick_address), - new Pick{f, d.ip, mac}, free_pick, static_cast(0)); - g_signal_connect_data(use_mac, "clicked", G_CALLBACK(on_pick_mac), new Pick{f, d.ip, mac}, + new Pick{f, d.ip}, free_pick, static_cast(0)); + g_signal_connect_data(use_mac, "clicked", G_CALLBACK(on_pick_mac), new Pick{f, mac}, free_pick, static_cast(0)); adw_expander_row_add_row(ADW_EXPANDER_ROW(f->scan_row), row); adw_expander_row_set_expanded(ADW_EXPANDER_ROW(f->scan_row), TRUE); @@ -284,7 +284,7 @@ gboolean on_scan_tick(gpointer user) { f.timer = 0; return G_SOURCE_REMOVE; } - const std::vector found = f.scan->poll(); + const auto& found = f.scan->poll(); // valid until f.scan.reset() below, after its last use while (f.results.size() < found.size()) add_result(fp, found[f.results.size()]); f.scan_ms += kTickMs; if (f.scan_ms < kScanMs) return G_SOURCE_CONTINUE; diff --git a/src/source/e1608/e1608_link.cpp b/src/source/e1608/e1608_link.cpp index bbb2c9a..e2a4371 100644 --- a/src/source/e1608/e1608_link.cpp +++ b/src/source/e1608/e1608_link.cpp @@ -291,7 +291,10 @@ const std::vector& Scan::poll() { socklen_t flen = sizeof from; const ssize_t n = ::recvfrom(s.get(), buf, sizeof buf, MSG_DONTWAIT, reinterpret_cast(&from), &flen); - if (n < 0) break; // nothing more on this socket for now + if (n < 0) { + if (errno == EINTR) continue; + break; // nothing more on this socket for now + } take_reply(buf, n, from, found_); } } diff --git a/src/source/e1608/e1608_source.cpp b/src/source/e1608/e1608_source.cpp index ebda74a..7e85e95 100644 --- a/src/source/e1608/e1608_source.cpp +++ b/src/source/e1608/e1608_source.cpp @@ -272,15 +272,15 @@ void E1608Source::connect_and_start() { Mac want{}; const bool have_mac = !cfg_.mac_text.empty() && parse_mac(cfg_.mac_text, want); if (host.empty() || have_mac) { - const std::vector targets = - host.empty() ? sweep_targets(cfg_.subnet) : std::vector{host}; const int wait_ms = std::min(cfg_.timeout_ms, 1500); // No address and no subnet: the limited broadcast, sent on every interface rather than only // the default route's. - const bool broadcast = - host.empty() && targets.size() == 1 && targets[0] == "255.255.255.255"; + const bool broadcast = host.empty() && cfg_.subnet.empty(); const std::vector found = - broadcast ? discover_broadcast(cfg_.port, wait_ms) : discover(targets, cfg_.port, wait_ms); + broadcast ? discover_broadcast(cfg_.port, wait_ms) + : discover(host.empty() ? sweep_targets(cfg_.subnet) + : std::vector{host}, + cfg_.port, wait_ms); if (host.empty()) { for (const DeviceInfo& d : found) { if (d.mac == want) host = d.ip;