Skip to content

feat(connection): resilient reconnect for changing networks + Disconnect button#21

Merged
HarryCordewener merged 1 commit into
fix/reconnect-auto-loginfrom
feat/connection-resilience
Jul 1, 2026
Merged

feat(connection): resilient reconnect for changing networks + Disconnect button#21
HarryCordewener merged 1 commit into
fix/reconnect-auto-loginfrom
feat/connection-resilience

Conversation

@HarryCordewener

Copy link
Copy Markdown
Member

Makes a session survive the network churn of a long drive (WiFi↔cellular, tower handoffs, dead zones) and adds a manual escape hatch. Implements the options discussed: #1 react to network changes, #2 survive long dead zones, #3 bind to the active network, #4 faster silent-death detection — plus a Disconnect button.

Stacked on #20 (re-send auto-login on reconnect) — base is fix/reconnect-auto-login so a reconnected session actually re-authenticates. Merge #20 first (or together); I'll retarget to master once it lands.

Core

Android

UI

  • Disconnect button in the session header — drops the connection / stops auto-reconnect, for when the client thinks it's connected but the socket is dead.

Tests

🤖 Generated with Claude Code

…ect button

Makes a session survive the network churn of a long drive (WiFi↔cellular, tower
handoffs, dead zones) and adds a manual escape hatch.

Core:
- ForceReconnectAsync() on TelnetConnection/ITelnetConnection — reconnect now to
  the last endpoint, tearing down the dead socket and any backoff; resumes even
  after auto-reconnect gave up (Error). No-op after an intentional disconnect.
- Tune TCP keepalive (30s idle / 10s interval / 3 probes) so a silently-dead peer
  surfaces in ~1 min instead of the OS default (~2h).
- Application-level IAC NOP heartbeat (45s) that keeps the server session alive
  and drops+reconnects when a write fails.
- ReconnectOptions.Default retries far longer (MaxAttempts 6 → 60, ~30 min) so a
  long dead zone doesn't permanently give up.
- Intentional DisconnectAsync + ForceReconnectAsync on ISession/Session.

Android:
- Keep-alive service now watches the DEFAULT network: on a change it pins the
  process to the new network (BindProcessToNetwork) and signals a reconnect;
  ConnectionKeepAliveCoordinator turns that into an immediate ForceReconnect on
  every session. NetworkChangeSignal bridges the two without the coordinator
  referencing Android-only types.

UI:
- Disconnect button in the session header (drops the connection / stops
  auto-reconnect) for when the client thinks it's connected but the socket is dead.

Builds off the reconnect auto-login fix so a reconnected session re-authenticates.
Core 198 / UI 47 / Data 17 tests pass; Android head builds clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HHCRc5CJ6595iMzEgYYdQp
@HarryCordewener
HarryCordewener merged commit ec4767b into fix/reconnect-auto-login Jul 1, 2026
2 checks passed
@HarryCordewener
HarryCordewener deleted the feat/connection-resilience branch July 1, 2026 13:36
HarryCordewener added a commit that referenced this pull request Jul 1, 2026
* fix(session): re-send auto-login on automatic reconnect

When a session dropped and TelnetConnection reconnected on its own, the stored
connect string was never re-sent — the launcher only sent it once, on the
initial connect. So an auto-reconnected session was left sitting at the server's
login screen (unauthenticated), and with an empty input box the Send button
stays disabled, leaving the user stuck.

Move the auto-login into the Session: it now runs on every transition into
Connected (initial connect AND each auto-reconnect) via a provider that resolves
the character's stored connect string from the secret store on demand. The
launcher supplies the provider and no longer sends the credential itself.

Adds SessionSendsAutoLoginOnConnectAndReconnect and
SessionWithoutAutoLoginSendsNothingOnConnect; full Core suite (196) passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HHCRc5CJ6595iMzEgYYdQp

* feat(connection): resilient reconnect for changing networks + Disconnect button (#21)

Makes a session survive the network churn of a long drive (WiFi↔cellular, tower
handoffs, dead zones) and adds a manual escape hatch.

Core:
- ForceReconnectAsync() on TelnetConnection/ITelnetConnection — reconnect now to
  the last endpoint, tearing down the dead socket and any backoff; resumes even
  after auto-reconnect gave up (Error). No-op after an intentional disconnect.
- Tune TCP keepalive (30s idle / 10s interval / 3 probes) so a silently-dead peer
  surfaces in ~1 min instead of the OS default (~2h).
- Application-level IAC NOP heartbeat (45s) that keeps the server session alive
  and drops+reconnects when a write fails.
- ReconnectOptions.Default retries far longer (MaxAttempts 6 → 60, ~30 min) so a
  long dead zone doesn't permanently give up.
- Intentional DisconnectAsync + ForceReconnectAsync on ISession/Session.

Android:
- Keep-alive service now watches the DEFAULT network: on a change it pins the
  process to the new network (BindProcessToNetwork) and signals a reconnect;
  ConnectionKeepAliveCoordinator turns that into an immediate ForceReconnect on
  every session. NetworkChangeSignal bridges the two without the coordinator
  referencing Android-only types.

UI:
- Disconnect button in the session header (drops the connection / stops
  auto-reconnect) for when the client thinks it's connected but the socket is dead.

Builds off the reconnect auto-login fix so a reconnected session re-authenticates.
Core 198 / UI 47 / Data 17 tests pass; Android head builds clean.


Claude-Session: https://claude.ai/code/session_01HHCRc5CJ6595iMzEgYYdQp

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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.

1 participant