When running multiple virtual printers with different access codes on
separate bind IPs, FTP connections were always routed to the wrong VP.
Root cause: the iptables REDIRECT rule (990→9990) rewrites the
destination IP to the incoming interface's primary address. With Linux's
weak host model (arp_filter=0), packets for secondary IPs arrive on the
primary interface, and REDIRECT sends them all to the first VP's FTP
server. MQTT was unaffected because port 8883 had no redirect.
Fix: FTP server now binds directly to port 990 (standard implicit FTPS),
eliminating the iptables redirect entirely. Requires CAP_NET_BIND_SERVICE
(already set in the systemd service file and Docker image).
Also removed a global asyncio set_exception_handler() in the MQTT server
that was overwritten by each VP instance, causing spurious "Unhandled
exception in client_connected_cb" errors on startup.
Changes:
- FTP_PORT: 9990 → 990 (ftp_server.py)
- Removed set_exception_handler() from MQTT server
- Updated Dockerfile, docker-compose.yml port mappings
- Deprecated --redirect-990 in install script
- Updated wiki: removed iptables instructions for all platforms
- Added migration guide (docs/migration-vp-ftp-port.md)
- Added unit tests for port constant and no-global-state invariant
X1C and X1 virtual printers used legacy SSDP model codes
(3DPrinter-X1-Carbon, 3DPrinter-X1) that BambuStudio doesn't
recognize, causing "incompatible printer preset" errors when
sending prints. Changed to the correct codes (BL-P001, BL-P002)
that real printers report via SSDP.
Also fixed proxy mode auto-inherit storing printer display names
(e.g. "X1C") instead of SSDP codes, by adding a resolution layer
that maps display names to model codes.
DB migration auto-converts existing VPs on startup.
The H2C dual nozzle variant reports model code O1C2 via MQTT, but only
O1C was recognized. This caused the camera to use the wrong protocol
(chamber image on port 6000 instead of RTSP on port 322), producing a
reconnect loop. Added O1C2 to all model ID maps across 8 files.
Large 3MF uploads intermittently failed with [Errno 104] Connection
reset by peer while the 16-byte verify_job always succeeded. The
_handle_data_connection callback returned immediately, letting the
asyncio task complete while cmd_STOR was still reading from the data
connection. The passive port listener also stayed open during transfers.
- Keep _handle_data_connection alive via _transfer_done event so the
asyncio task holds strong references throughout the transfer
- Close passive port listener after accepting the data connection
- Reject duplicate data connections with a warning log
- Add drain timeout (5s) to MQTT status pushes to prevent blocking
when the slicer is busy with FTP upload
- Improve error logging with bytes received and exception type
Enable Bambu Studio on a remote network to print through BamBuddy
acting as a TLS-terminating proxy for both MQTT and FTP connections.
- Add TLSProxy base class and FTPTLSProxy with PASV response rewriting,
EPSV→PASV translation, PROT P/C tracking, and one-shot data proxies
- Add SlicerProxyManager to coordinate per-slicer MQTT + FTP proxy pairs
- Support additional SAN IPs in certificate generation for proxy mode
- Broadcast SSDP on LAN B so slicers discover the proxy as a printer
- Narrow FTP passive port range to 50000-50100 with retry logic
- Expose proxy ports (8883, 9990, 50000-50100) in Dockerfile
- Document passive port range in docker-compose.yml
- Correct SSDP model codes: C11=P1P, C12=P1S, N7=P2S, C13=X1E
- Fix serial prefixes based on actual Bambu serial format
- Add confirmation modal for pending upload discard
- Sort model dropdown alphabetically, remove internal codes
- Add "Setup Required" warning with link to wiki documentation
- Update wiki with certificate installation and platform setup guides
- Virtual printer appears in Bambu Studio/Orca Slicer via SSDP discovery
- Secure TLS/MQTT communication with auto-generated certificates
- Queue mode (pending uploads) or auto-start mode
- Configurable access code for authentication
- Docker support with network_mode: host and certificate persistence
- Fix backup/restore for virtual printer settings (auto-save no longer overwrites)