Skip to content

Commit 4b3800a

Browse files
committed
v0.8.6: armhf glibc pin + Check-for-updates button (#15)
=== PR #14 follow-up: armhf build runs on Pi Bookworm/Bullseye === PR #14 (merged earlier) added arm-unknown-linux-gnueabihf to the release matrix but pinned os=ubuntu-latest, which is 24.04 with GLIBC 2.39. Target armhf sysroot on 24.04 is Debian Trixie (GLIBC 2.39), far too new for a Raspberry Pi 2/3 on Bookworm (2.36) or Bullseye (2.31) — users would get 'GLIBC_2.39 not found' the same way the Linux-amd64 issue #2 folks did before we pinned them to 22.04. Fix: pin the armhf matrix entry to ubuntu-22.04, matching our other linux-gnu targets. Binary will link against GLIBC 2.35 max, which loads on Pi Bookworm and Bullseye. Also trimmed two trailing spaces. Locally verified the cross-compile: rust:latest + gcc-arm-linux- gnueabihf + proper CARGO_HOME config.toml produces a valid ARM 32-bit ELF (2.9 MB, armhf EABI5). === Issue #15: 'Check for updates' button in the UI === New src/update_check.rs module. On the user's click (no polling): 1. Tcp-probes github.com:443 with a 5s budget. If unreachable, we return Offline(reason) instead of a confusing 'update check failed' — distinguishes 'you're offline' from 'GitHub API misbehaved'. 2. HTTPS GET api.github.com/repos/.../releases/latest via the tokio + rustls stack (same hand-rolled HTTP pattern as domain_fronter — no new crate deps). Parses tag_name, strips the v-prefix, loose-semver-compares to env!(CARGO_PKG_VERSION). 3. Returns one of four UpdateCheck variants: Offline / Error / UpToDate / UpdateAvailable { release_url }. New UI wiring (src/bin/ui.rs): - Cmd::CheckUpdate enqueue variant - UiState::last_update_check { InFlight, Done(result) } - 'Check for updates' button next to the CA buttons - Result displayed as a colored small-text line under the CA info: green 'up to date', amber 'update available v0.8.5 → v0.8.6' with a clickable release-page hyperlink, red for offline/error. Verified end-to-end with a live github.com fetch (got a rate-limit HTTP 403 from my IP because I've been hitting the API a lot, but that's the expected Error() state — response classification was correct). Three unit tests for is_newer() and a gated live test for the full round-trip. 43 tests pass.
1 parent 013edfb commit 4b3800a

6 files changed

Lines changed: 412 additions & 5 deletions

File tree

.github/workflows/release.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ jobs:
2727
os: ubuntu-22.04
2828
name: mhrv-rs-linux-arm64
2929
- target: arm-unknown-linux-gnueabihf
30-
os: ubuntu-latest
31-
name: mhrv-rs-raspbian-armhf
30+
os: ubuntu-22.04
31+
name: mhrv-rs-raspbian-armhf
3232
- target: x86_64-apple-darwin
3333
os: macos-latest
3434
name: mhrv-rs-macos-amd64
@@ -82,7 +82,7 @@ jobs:
8282
sudo apt-get update
8383
sudo apt-get install -y gcc-arm-linux-gnueabihf
8484
echo '[target.arm-unknown-linux-gnueabihf]' >> ~/.cargo/config.toml
85-
echo 'linker = "arm-linux-gnueabihf-gcc"' >> ~/.cargo/config.toml
85+
echo 'linker = "arm-linux-gnueabihf-gcc"' >> ~/.cargo/config.toml
8686
8787
- name: Install Windows MinGW toolchain
8888
if: matrix.target == 'x86_64-pc-windows-gnu'

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mhrv-rs"
3-
version = "0.8.5"
3+
version = "0.8.6"
44
edition = "2021"
55
description = "Rust port of MasterHttpRelayVPN -- DPI bypass via Google Apps Script relay with domain fronting"
66
license = "MIT"

src/bin/ui.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,16 @@ struct UiState {
9090
last_test_msg: String,
9191
/// Per-SNI probe results, populated by Cmd::TestSni / TestAllSni.
9292
sni_probe: HashMap<String, SniProbeState>,
93+
/// Most recent result of the Check-for-updates button (issue #15).
94+
/// `None` = never checked this session. `Some(InFlight)` during the
95+
/// probe, then the resolved outcome.
96+
last_update_check: Option<UpdateProbeState>,
97+
}
98+
99+
#[derive(Clone, Debug)]
100+
enum UpdateProbeState {
101+
InFlight,
102+
Done(mhrv_rs::update_check::UpdateCheck),
93103
}
94104

95105
#[derive(Clone, Debug)]
@@ -118,6 +128,9 @@ enum Cmd {
118128
google_ip: String,
119129
snis: Vec<String>,
120130
},
131+
/// Hit github.com + the Releases API and compare the running version
132+
/// to the latest tag. Result is written to UiState::last_update_check.
133+
CheckUpdate,
121134
}
122135

123136
struct App {
@@ -766,6 +779,17 @@ impl eframe::App for App {
766779
if ui.button("Check CA").clicked() {
767780
let _ = self.cmd_tx.send(Cmd::CheckCaTrusted);
768781
}
782+
783+
if ui.button("Check for updates")
784+
.on_hover_text(
785+
"Ping github.com, then ask the Releases API for the latest tag and \
786+
compare against this running version. No background polling — only \
787+
fires when you click this button."
788+
)
789+
.clicked()
790+
{
791+
let _ = self.cmd_tx.send(Cmd::CheckUpdate);
792+
}
769793
});
770794

771795
if !last_test_msg.is_empty() {
@@ -796,6 +820,38 @@ impl eframe::App for App {
796820
));
797821
}
798822

823+
// Update-check result (issue #15): only shown after the user
824+
// clicks "Check for updates". No background polling.
825+
if let Some(state) = &self.shared.state.lock().unwrap().last_update_check.clone() {
826+
match state {
827+
UpdateProbeState::InFlight => {
828+
ui.small(egui::RichText::new("Checking for updates…")
829+
.color(egui::Color32::GRAY));
830+
}
831+
UpdateProbeState::Done(r) => {
832+
use mhrv_rs::update_check::UpdateCheck;
833+
let (txt, color) = match r {
834+
UpdateCheck::UpToDate { .. } => (
835+
r.summary(),
836+
egui::Color32::from_rgb(80, 180, 100),
837+
),
838+
UpdateCheck::UpdateAvailable { .. } => (
839+
r.summary(),
840+
egui::Color32::from_rgb(220, 170, 80),
841+
),
842+
UpdateCheck::Offline(_) | UpdateCheck::Error(_) => (
843+
r.summary(),
844+
egui::Color32::from_rgb(220, 110, 110),
845+
),
846+
};
847+
ui.small(egui::RichText::new(txt).color(color));
848+
if let UpdateCheck::UpdateAvailable { release_url, .. } = r {
849+
ui.hyperlink_to("Open release page", release_url);
850+
}
851+
}
852+
}
853+
}
854+
799855
ui.separator();
800856
ui.label(egui::RichText::new("Recent log").strong());
801857
egui::ScrollArea::vertical()
@@ -1248,6 +1304,17 @@ fn background_thread(shared: Arc<Shared>, rx: Receiver<Cmd>) {
12481304
shared2.state.lock().unwrap().ca_trusted = Some(trusted);
12491305
});
12501306
}
1307+
Ok(Cmd::CheckUpdate) => {
1308+
let shared2 = shared.clone();
1309+
shared2.state.lock().unwrap().last_update_check =
1310+
Some(UpdateProbeState::InFlight);
1311+
rt.spawn(async move {
1312+
let result = mhrv_rs::update_check::check().await;
1313+
push_log(&shared2, &format!("[ui] update check: {}", result.summary()));
1314+
shared2.state.lock().unwrap().last_update_check =
1315+
Some(UpdateProbeState::Done(result));
1316+
});
1317+
}
12511318
Err(_) => {}
12521319
}
12531320

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ pub mod rlimit;
1111
pub mod scan_ips;
1212
pub mod scan_sni;
1313
pub mod test_cmd;
14+
pub mod update_check;

0 commit comments

Comments
 (0)