Skip to content

serial: bidirectional TCP sink (mode = "tcp")#121

Merged
LinuxJedi merged 2 commits into
LinuxJedi:mainfrom
codewiz:feat/serial-tcp
Jul 6, 2026
Merged

serial: bidirectional TCP sink (mode = "tcp")#121
LinuxJedi merged 2 commits into
LinuxJedi:mainfrom
codewiz:feat/serial-tcp

Conversation

@codewiz

@codewiz codewiz commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Adds a fourth [serial] mode bridging Paula's serial port to a host TCP listener, like UAE's TCP: serial device (same default port, 1234; override with [serial] listen = "host:port").

With Mount AUX: + NewShell AUX: on the Amiga side, a connected client gets a full remote AmigaDOS console -- handy for scripted testing and for driving the emulated machine headlessly. One client at a time; a new connection replaces a finished one, and output with no client connected is dropped like an unplugged cable.

Implementation notes:

  • A background thread owns the accept loop and the socket read half, staging input bytes through a channel with an atomic fill counter, so Paula's idle fast path (has_pending_input) stays a cheap atomic load and never touches a socket.
  • Writes go directly to the client stream with TCP_NODELAY for shell interactivity.
  • Zero new dependencies (std::net only), so it works on all platforms, unlike a pty-based bridge.
  • Unit test covers the input/output round trip; tested interactively against an AUX: shell with minicom (via a pty bridge) and scripted clients.

🤖 Generated with Claude Code

@codewiz

codewiz commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

I have regrets about using TCP: I couldn't get a working Amiga shell with nc nor with screen, probably due to mismatches between VT100-ish terminal escapes and the ANSI escapes used by the shell.

Amiberry / WinUAE also relay the built-in serial to localhost:1234, which is probably a good choice for file transfers and modem emulation, but I think we should also have a pty mode that works directly with minicom -D /tmp/amiga-serial.

Copilot AI left a comment

Copy link
Copy Markdown

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 adds a new [serial] mode = "tcp" option that bridges the emulated Paula serial port to a host TCP listener (defaulting to 127.0.0.1:1234, configurable via [serial] listen), enabling bidirectional I/O suitable for remote AmigaDOS AUX: shells and headless/scripting workflows.

Changes:

  • Introduces TcpSerialSink implementing a bidirectional TCP serial bridge with a background accept/read thread and a fast has_pending_input() probe.
  • Extends configuration parsing/serialization to support SerialMode::Tcp and the optional [serial] listen address.
  • Updates the launcher’s serial mode labeling/cycling to include the new TCP mode (in MIDI-feature builds).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
src/video/launcher.rs Adds TCP to the launcher’s serial mode cycle/label list.
src/serial.rs Implements the new bidirectional TCP serial sink and a unit test for round-tripping.
src/emulator.rs Wires SerialMode::Tcp into serial sink construction using the configured/default listen address.
src/config.rs Adds SerialMode::Tcp, [serial] listen, and parsing/error-message updates.

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

Comment thread src/serial.rs Outdated
Comment thread src/serial.rs
Comment thread src/video/launcher.rs
Comment thread src/serial.rs
@codewiz

codewiz commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review - all four addressed in 582d7cf:

  • buffered unsigned underflow (both comments): switched to AtomicIsize, so a read_byte that consumes a byte before the reader thread's matching fetch_add dips to a transient -1 debt instead of wrapping to usize::MAX and getting stuck-true.
  • nc hint mangles IPv6: now formats local_addr.ip()/local_addr.port() separately (and uses the resolved local_addr, so port-0 binds print the real port).
  • launcher drops [serial] listen on re-save: MachineSetup now carries serial_listen through from_raw/to_raw; added a round-trip regression test.

@LinuxJedi

Copy link
Copy Markdown
Owner

Sorry @codewiz, just merged a bunch of things and it caused a merge conflict. Can you sort that and then I should be able to get this in.

Bridges Paula's serial port to a host TCP listener, like UAE's TCP:
serial device (same default port 1234; override with [serial] listen).
With an AUX: shell on the Amiga side this gives a remote AmigaDOS
console.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@codewiz codewiz force-pushed the feat/serial-tcp branch from 582d7cf to 4654192 Compare July 6, 2026 15:24
@codewiz

codewiz commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

No problem - rebased onto current main (the conflict was just the new [audio] lines landing next to the [serial] block in MachineSetup::to_raw). Builds clean, fmt/clippy happy, serial tests pass. Ready when you are.

- buffered: AtomicIsize so a read that races ahead of the reader
  thread's fetch_add dips to a -1 debt instead of wrapping usize.
- nc hint: format local_addr ip()/port() separately, IPv6-safe.
- launcher: carry [serial] listen through MachineSetup so a save
  no longer drops the override; add a round-trip test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@codewiz codewiz force-pushed the feat/serial-tcp branch from 4654192 to 8a068c6 Compare July 6, 2026 15:29

@LinuxJedi LinuxJedi left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Excellent stuff!

@LinuxJedi LinuxJedi merged commit 23f314f into LinuxJedi:main Jul 6, 2026
8 checks passed
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