Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,36 @@ jobs:
# locally from an elevated shell.
- name: Compile tests
run: cargo test --no-run --locked

check-linux:
name: clippy + build + tests (Linux)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: clippy

# eframe/tray pull in GTK, libxdo and the Ayatana app-indicator at build
# time; the runner image doesn't ship their -dev packages.
- name: Install system libraries
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libxdo-dev libayatana-appindicator3-dev pkg-config

- name: Cache cargo build
uses: Swatinem/rust-cache@v2

- name: Clippy
run: cargo clippy --all-targets --locked -- -D warnings

- name: Build
run: cargo build --locked

# No requireAdministrator manifest on Linux, so the tests actually run
# here (the Windows job can only compile them).
- name: Tests
run: cargo test --locked
44 changes: 38 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ date while you play ARC Raiders. It signs you into ARCTracker, helps you start
the game from Steam or Epic, and then connects your game account so ARCTracker
can sync your inventory automatically in the background.

It runs as a small Windows desktop app with a tray icon. Once it's set up, you
mostly leave it alone — open it, start your game, and play.
It runs as a small desktop app — a polished Windows build with a tray icon, plus
a build-from-source option for Linux (ARC Raiders via Proton). Once it's set up,
you mostly leave it alone — open it, start your game, and play.

> **License:** ARCTracker Sync is **free for noncommercial use** under the
> PolyForm Noncommercial License 1.0.0. **Commercial use requires a separate
Expand Down Expand Up @@ -59,10 +60,12 @@ ARCTracker sign-in is kept in Windows Credential Manager.
### Why it needs Administrator

To notice your game account connecting, ARCTracker Sync watches your own
computer's network traffic using Windows raw sockets, which Windows only allows
with Administrator rights. By default there's no kernel driver, bundled network
library, or extra capture tool to install — and it only ever looks at traffic on
your own machine.
computer's network traffic using raw sockets, which the OS only allows with
elevated privileges. On Windows that means Administrator rights; on Linux it
means the `CAP_NET_RAW` capability (granted with a one-time `setcap`, or by
running as root) — see [Linux](#linux-arc-raiders-via-proton). By default
there's no kernel driver, bundled network library, or extra capture tool to
install — and it only ever looks at traffic on your own machine.

### Optional: Npcap capture

Expand Down Expand Up @@ -100,6 +103,35 @@ The app ships a manifest that requests elevation, so it runs as Administrator
external tooling is needed for the default raw-socket capture; the optional
Npcap capture method uses Npcap's driver, installed separately by the user.

### Linux (ARC Raiders via Proton)

Windows is the primary, prebuilt target. Linux is supported as a
**build-from-source** option for running ARC Raiders through Proton — there is
no Linux release binary, so you compile it yourself. The audience here is
already comfortable in a terminal (you're running a Proton game), so this is a
script, not an installer.

Prerequisites:

- A stable Rust toolchain (install via [rustup](https://rustup.rs/)).
- The GUI's system libraries: GTK 3, libxdo, and the Ayatana app-indicator
(`libgtk-3-dev`, `libxdo-dev`, `libayatana-appindicator3-dev` on Debian/Ubuntu;
the equivalents on your distro).
- ARC Raiders on **Steam** (the Epic launcher isn't supported on Linux).

From the repository root:

```bash
./scripts/run-linux.sh
```

That builds the release binary, grants it `CAP_NET_RAW` with a one-time
`sudo setcap cap_net_raw+ep` (so the GUI itself runs unprivileged, the Linux
equivalent of the Windows Administrator requirement), and launches it.

See [docs/LINUX.md](docs/LINUX.md) for how capture works under Proton, the
`SSLKEYLOGFILE` setup, a capture smoke test, and current caveats.

## Contributing

Bug reports, feature ideas, and pull requests are welcome. See
Expand Down
73 changes: 73 additions & 0 deletions examples/capture_smoke.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//! Capture smoke test: lists interfaces, opens the first non-loopback one, and
//! reports how many frames and TCP/443 segments arrive over a few seconds.
//!
//! It exercises the live capture backend end to end (interface enumeration,
//! socket open, frame read, link-layer strip, TCP/443 filter) without the GUI
//! or any game, so a non-zero TCP/443 count while browsing HTTPS means capture
//! works on this machine. Needs CAP_NET_RAW (run as root, or after
//! `setcap cap_net_raw+ep` on the binary).
//!
//! cargo run --release --example capture_smoke [interface] [seconds]

use std::time::{Duration, Instant};

use anyhow::{Context, Result};
use arctracker_sync::packet::{datalink_name, parse_tcp_segment};
use arctracker_sync::rawsock::RawSock;

fn main() -> Result<()> {
let mut args = std::env::args().skip(1);
let wanted = args.next();
let seconds: u64 = args.next().and_then(|s| s.parse().ok()).unwrap_or(5);

let sock = RawSock::load().context("loading capture backend")?;
let devices = sock.list_devices().context("listing interfaces")?;
if devices.is_empty() {
anyhow::bail!("no capture interfaces found");
}

println!("Interfaces:");
for device in &devices {
let desc = device.description.as_deref().unwrap_or("");
println!(" {} {}", device.name, desc);
}

let chosen = match &wanted {
Some(name) => devices
.iter()
.find(|d| &d.name == name)
.with_context(|| format!("interface {name:?} not found"))?,
None => &devices[0],
};
println!("\nOpening {} for {seconds}s ...", chosen.name);

let mut capture = sock
.open_live(&chosen.name)
.with_context(|| format!("opening {}", chosen.name))?;
let datalink = capture.datalink()?;
capture.set_filter("tcp port 443").ok();
println!("Datalink: {} ({datalink})", datalink_name(datalink));

let started = Instant::now();
let mut frames = 0u64;
let mut https = 0u64;
while started.elapsed() < Duration::from_secs(seconds) {
if let Some(packet) = capture.next_packet()? {
frames += 1;
if parse_tcp_segment(frames, packet.timestamp_us, datalink, &packet.data)?.is_some() {
https += 1;
}
}
}

println!("\nframes captured: {frames}");
println!("TCP/443 segments: {https}");
if https > 0 {
println!("OK: live TCP/443 capture works on this interface.");
} else if frames > 0 {
println!("Frames seen but no TCP/443 — browse an HTTPS site while this runs.");
} else {
println!("No frames — wrong interface, or CAP_NET_RAW is missing.");
}
Ok(())
}
7 changes: 7 additions & 0 deletions locales/da.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"SyncApp.footer.settings": "Indstillinger",
"SyncApp.state.needsAdmin.title": "En hurtig tilladelse først",
"SyncApp.state.needsAdmin.body": "ARCTracker Sync skal køre som administrator for at læse dit inventar mens du spiller. Genstarte det med administratoradgang for at fortsætte.",
"SyncApp.state.needsAdmin.bodyLinux": "ARCTracker Sync skal have tilladelse til at opsamle netværkstrafik for at læse dit inventar mens du spiller. Giv det opsamlingsadgang (CAP_NET_RAW) for at fortsætte.",
"SyncApp.state.signedOut.title": "Velkommen til ARCTracker Sync",
"SyncApp.state.signedOut.body": "Log ind for at forbinde din ARCTracker-konto. Når det er sat op, opdateres dit ARC Raiders-inventar automatisk mens du spiller.",
"SyncApp.state.signingIn.title": "Afslut login…",
Expand All @@ -48,7 +49,9 @@
"SyncApp.state.synced.body": "Spiller som %{account}. Dit ARC Raiders-inventar er opdateret på ARCTracker.",
"SyncApp.state.synced.session": "Dit inventar forbliver synkroniseret indtil %{time}.",
"SyncApp.state.synced.canClose": "Du kan lukke ARCTracker Sync og blive ved med at spille. Lad det køre i systemstatusfeltet for at blive ved med at synkronisere hele sessionnen.",
"SyncApp.state.synced.canCloseLinux": "Hold dette vindue åbent mens du spiller — ARCTracker Sync holder dit inventar synkroniseret hele sessionnen.",
"SyncApp.state.syncedIdle.body": "Venter på din næste ARC Raiders-session. ARCTracker Sync kører videre i systemstatusfeltet.",
"SyncApp.state.syncedIdle.bodyLinux": "Venter på din næste ARC Raiders-session. Hold ARCTracker Sync kørende.",
"SyncApp.state.needsLauncher.title": "%{launcher} skal forberes igen",
"SyncApp.state.needsLauncher.body": "%{launcher} blev genstartet på egen hånd, så ARCTracker kan ikke læse dit inventar lige nu. Forbered det igen for at fortsætte synkroniseringen.",
"SyncApp.state.needsAttention.title": "Synkronisering kræver opmærksomhed",
Expand All @@ -65,6 +68,7 @@
"SyncApp.action.getHelp": "Få hjælp",
"SyncApp.action.tryAgain": "Prøv igen",
"SyncApp.action.restartAsAdmin": "Genstart som administrator",
"SyncApp.action.grantCapture": "Giv opsamlingsadgang",
"SyncApp.action.gotIt": "Forstået",
"SyncApp.explain.title": "Hvad betyder forberedelsen af %{launcher}",
"SyncApp.explain.body": "ARCTracker holder dit ARC Raiders-inventar opdateret på hjemmesiden automatisk mens du spiller. For at sætte det op, åbner det %{launcher} igen, bare få sekunder, så spillet kan forbinde til appen.\n\nMens du spiller, henter ARCTracker Sync en midlertidig adgangsnøgle fra spillet og sender den til ARCTracker, som bruger den til at læse dit inventar for dig. Nøglen udløber af sig selv og er aldrig dit %{launcher} eller ARC Raiders-password.\n\nDin %{launcher}-konto røres ikke. Dine spil, downloads, venner og login forbliver nøjagtigt som de er. Alt kører på din pc; det eneste, der sendes til ARCTracker, er den midlertidige nøgle.",
Expand All @@ -83,14 +87,17 @@
"SyncApp.settings.language": "Sprog",
"SyncApp.settings.displayLanguage": "Visningssprog",
"SyncApp.settings.matchesWindows": "Svarer til Windows som standard",
"SyncApp.settings.matchesSystem": "Svarer til dit system som standard",
"SyncApp.settings.matchWindows": "Svar til Windows",
"SyncApp.settings.matchSystem": "Svar til system",
"SyncApp.settings.network": "Netværk",
"SyncApp.settings.networkAdapter": "Netværkskort",
"SyncApp.settings.networkAdapterSub": "Auto-valgt. Skift kun hvis synkronisering ikke forbindes.",
"SyncApp.settings.refresh": "Opdater",
"SyncApp.settings.captureMethod": "Opsamlingsmetode",
"SyncApp.settings.captureMethodSub": "Sådan læser Sync din pc's egen spiltrafik. Skift til Npcap, hvis antivirussoftware blokerer den indbyggede metode — det kan også fungere bedre, hvis du bruger en VPN eller proxy.",
"SyncApp.settings.captureRawSockets": "Windows raw sockets (indbygget)",
"SyncApp.settings.captureRawSocketsLinux": "Raw sockets (AF_PACKET, indbygget)",
"SyncApp.settings.captureNpcap": "Npcap (installeres separat)",
"SyncApp.settings.npcapMissing": "Npcap er ikke installeret, så synkronisering kan ikke opsamle trafik. Installer det, og brug derefter Prøv igen på hovedskærmen.",
"SyncApp.settings.npcapLink": "Hent Npcap (gratis) på npcap.com",
Expand Down
7 changes: 7 additions & 0 deletions locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"SyncApp.footer.settings": "Einstellungen",
"SyncApp.state.needsAdmin.title": "Zunächst eine kurze Berechtigung",
"SyncApp.state.needsAdmin.body": "ARCTracker Sync benötigt Administratorrechte, um dein Inventar während des Spielens zu lesen. Starten Sie es mit Administratorzugriff neu, um fortzufahren.",
"SyncApp.state.needsAdmin.bodyLinux": "ARCTracker Sync benötigt Berechtigung zum Erfassen von Netzwerkverkehr, um dein Inventar während des Spielens zu lesen. Gewähre ihm Erfassungszugriff (CAP_NET_RAW), um fortzufahren.",
"SyncApp.state.signedOut.title": "Willkommen bei ARCTracker Sync",
"SyncApp.state.signedOut.body": "Melde dich an, um dein ARCTracker-Konto zu verbinden. Nach der Einrichtung wird dein ARC Raiders-Inventar während des Spiels automatisch aktualisiert.",
"SyncApp.state.signingIn.title": "Anmeldung wird abgeschlossen…",
Expand All @@ -48,7 +49,9 @@
"SyncApp.state.synced.body": "Spielt als %{account}. Dein ARC Raiders-Inventar ist auf ARCTracker aktuell.",
"SyncApp.state.synced.session": "Dein Inventar bleibt bis %{time} synchronisiert.",
"SyncApp.state.synced.canClose": "Du kannst ARCTracker Sync schließen und weiterspielen. Lass es im Hintergrund laufen, um während deiner ganzen Sitzung synchronisiert zu bleiben.",
"SyncApp.state.synced.canCloseLinux": "Lass dieses Fenster während des Spielens offen — ARCTracker Sync hält dein Inventar während der gesamten Sitzung synchronisiert.",
"SyncApp.state.syncedIdle.body": "Wartet auf deine nächste ARC Raiders-Sitzung. ARCTracker Sync läuft im Hintergrund weiter.",
"SyncApp.state.syncedIdle.bodyLinux": "Wartet auf deine nächste ARC Raiders-Sitzung. ARCTracker Sync läuft weiter.",
"SyncApp.state.needsLauncher.title": "%{launcher} muss wieder vorbereitet werden",
"SyncApp.state.needsLauncher.body": "%{launcher} wurde von selbst neu gestartet, daher kann ARCTracker dein Inventar momentan nicht lesen. Bereite es erneut vor, um die Synchronisierung weiterhin zu gewährleisten.",
"SyncApp.state.needsAttention.title": "Synchronisierung benötigt Aufmerksamkeit",
Expand All @@ -65,6 +68,7 @@
"SyncApp.action.getHelp": "Hilfe erhalten",
"SyncApp.action.tryAgain": "Nochmal versuchen",
"SyncApp.action.restartAsAdmin": "Als Administrator neu starten",
"SyncApp.action.grantCapture": "Erfassungszugriff gewähren",
"SyncApp.action.gotIt": "Verstanden",
"SyncApp.explain.title": "Was %{launcher} vorbereiten bewirkt",
"SyncApp.explain.body": "ARCTracker hält dein ARC Raiders-Inventar auf der Website automatisch aktuell, während du spielst. Um das einzurichten, öffnet es %{launcher} einmal neu, nur wenige Sekunden, damit das Spiel sich mit der App verbinden kann.\n\nWährend du spielst, holt ARCTracker Sync einen temporären Zugangsschlüssel aus dem Spiel und leitet ihn an ARCTracker weiter, das ihn nutzt, um dein Inventar für dich zu lesen. Der Schlüssel verfällt von selbst und ist niemals dein %{launcher}- oder ARC Raiders-Passwort.\n\nDein %{launcher}-Konto wird nicht berührt. Deine Spiele, Downloads, Freunde und Anmeldung bleiben genau wie sie sind. Alles läuft auf deinem PC. Das einzige, das an ARCTracker versendet wird, ist dieser temporäre Schlüssel.",
Expand All @@ -83,14 +87,17 @@
"SyncApp.settings.language": "Sprache",
"SyncApp.settings.displayLanguage": "Anzeigesprache",
"SyncApp.settings.matchesWindows": "Entspricht standardmäßig Windows",
"SyncApp.settings.matchesSystem": "Entspricht standardmäßig deinem System",
"SyncApp.settings.matchWindows": "Windows abgleichen",
"SyncApp.settings.matchSystem": "System abgleichen",
"SyncApp.settings.network": "Netzwerk",
"SyncApp.settings.networkAdapter": "Netzwerkadapter",
"SyncApp.settings.networkAdapterSub": "Automatisch ausgewählt. Nur ändern, wenn Sync sich nicht verbindet.",
"SyncApp.settings.refresh": "Aktualisieren",
"SyncApp.settings.captureMethod": "Erfassungsmethode",
"SyncApp.settings.captureMethodSub": "Wie Sync den eigenen Spielverkehr deines PCs liest. Wechsle zu Npcap, wenn Antivirensoftware die integrierte Methode blockiert — es kann auch besser funktionieren, wenn du ein VPN oder einen Proxy verwendest.",
"SyncApp.settings.captureRawSockets": "Windows Raw Sockets (integriert)",
"SyncApp.settings.captureRawSocketsLinux": "Raw Sockets (AF_PACKET, integriert)",
"SyncApp.settings.captureNpcap": "Npcap (separat installiert)",
"SyncApp.settings.npcapMissing": "Npcap ist nicht installiert, daher kann die Synchronisierung keinen Datenverkehr erfassen. Installiere es und nutze dann „Nochmal versuchen“ auf dem Hauptbildschirm.",
"SyncApp.settings.npcapLink": "Npcap (kostenlos) auf npcap.com herunterladen",
Expand Down
7 changes: 7 additions & 0 deletions locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"SyncApp.footer.settings": "Settings",
"SyncApp.state.needsAdmin.title": "One quick permission first",
"SyncApp.state.needsAdmin.body": "ARCTracker Sync needs to run as administrator to read your inventory while you play. Restart it with administrator access to continue.",
"SyncApp.state.needsAdmin.bodyLinux": "ARCTracker Sync needs permission to capture network traffic to read your inventory while you play. Grant it capture access (CAP_NET_RAW) to continue.",
"SyncApp.state.signedOut.title": "Welcome to ARCTracker Sync",
"SyncApp.state.signedOut.body": "Sign in to connect your ARCTracker account. Once set up, your ARC Raiders inventory stays up to date automatically while you play.",
"SyncApp.state.signingIn.title": "Finish signing in…",
Expand All @@ -48,7 +49,9 @@
"SyncApp.state.synced.body": "Playing as %{account}. Your ARC Raiders inventory is up to date on ARCTracker.",
"SyncApp.state.synced.session": "Your inventory stays synced until %{time}.",
"SyncApp.state.synced.canClose": "You can close this window and keep playing — ARCTracker Sync stays in the tray and keeps your stash synced all session.",
"SyncApp.state.synced.canCloseLinux": "Keep this window open while you play — ARCTracker Sync keeps your stash synced all session.",
"SyncApp.state.syncedIdle.body": "Waiting for your next ARC Raiders session. ARCTracker Sync keeps running in the tray.",
"SyncApp.state.syncedIdle.bodyLinux": "Waiting for your next ARC Raiders session. Keep ARCTracker Sync running.",
"SyncApp.state.needsLauncher.title": "%{launcher} needs preparing again",
"SyncApp.state.needsLauncher.body": "%{launcher} was restarted on its own, so ARCTracker can't read your inventory right now. Prepare it again to keep syncing.",
"SyncApp.state.needsAttention.title": "Sync needs attention",
Expand All @@ -65,6 +68,7 @@
"SyncApp.action.getHelp": "Get help",
"SyncApp.action.tryAgain": "Try again",
"SyncApp.action.restartAsAdmin": "Restart as administrator",
"SyncApp.action.grantCapture": "Grant capture access",
"SyncApp.action.gotIt": "Got it",
"SyncApp.explain.title": "What preparing %{launcher} does",
"SyncApp.explain.body": "ARCTracker keeps your ARC Raiders inventory up to date on the website automatically while you play. To set that up, it reopens %{launcher} once, just for a few seconds, so the game can connect to the app.\n\nWhile you play, ARCTracker Sync picks up a temporary access key from the game and passes it to ARCTracker, which uses it to read your inventory for you. The key expires on its own and is never your %{launcher} or ARC Raiders password.\n\nYour %{launcher} account isn't touched. Your games, downloads, friends, and sign-in stay exactly as they are. Everything runs on your PC; the only thing sent to ARCTracker is that temporary key.",
Expand All @@ -84,13 +88,16 @@
"SyncApp.settings.displayLanguage": "Display language",
"SyncApp.settings.matchesWindows": "Matches Windows by default",
"SyncApp.settings.matchWindows": "Match Windows",
"SyncApp.settings.matchesSystem": "Matches your system by default",
"SyncApp.settings.matchSystem": "Match system",
"SyncApp.settings.network": "Network",
"SyncApp.settings.networkAdapter": "Network adapter",
"SyncApp.settings.networkAdapterSub": "Auto-selected. Only change it if sync won't connect.",
"SyncApp.settings.refresh": "Refresh",
"SyncApp.settings.captureMethod": "Capture method",
"SyncApp.settings.captureMethodSub": "How Sync reads your PC's own game traffic. Switch to Npcap if antivirus software blocks the built-in method — it may also work better if you use a VPN or proxy.",
"SyncApp.settings.captureRawSockets": "Windows raw sockets (built in)",
"SyncApp.settings.captureRawSocketsLinux": "Raw sockets (AF_PACKET, built in)",
"SyncApp.settings.captureNpcap": "Npcap (installed separately)",
"SyncApp.settings.npcapMissing": "Npcap isn't installed, so sync can't capture traffic. Install it, then use Try again on the main screen.",
"SyncApp.settings.npcapLink": "Get Npcap (free) at npcap.com",
Expand Down
Loading
Loading