Redesign ProxyEngine as a bounded asynchronous TCP proxy
Replace ProxyEngine's callback-based NetCoreServer forwarding with a native .NET 8 asynchronous TCP proxy while preserving the public port map and trusted SessionInfo protocol. Requirements: - One atomic two-session-per-source-IP limit shared across playfield ports 8501-8504; login 7000 and chat 7005 do not consume those slots. - Reject before backend connection and payload forwarding. Release slots exactly once under disconnects, failures, and shutdown. - Write the trusted SessionInfo record completely before reading any client payload. - Use bounded pooled buffers and natural TCP backpressure in both directions; handle partial sends and avoid synchronous socket I/O/per-packet logging allocations. - Bound backend connection setup, propagate either-side disconnect promptly, configure low-latency keepalive sockets, and shut down listeners/sessions gracefully. - Keep deployment behavior and self-contained Linux publishing. Add meaningful concurrency, ordering, forwarding, timeout/failure, cleanup, and CI tests. Acceptance: - Cross-port concurrent admissions cannot exceed two; login/chat remain unaffected and disconnected slots are reusable. - Backend always observes SessionInfo before client bytes. - Large bidirectional payloads are transferred byte-for-byte through bounded async pumps. - Backend failures and process shutdown close clients and release tracked sessions without unobserved failures. - Strict Release build, tests, CI-equivalent .NET 8 container build, and self-contained publish pass. Implemented and verified; changes are committed on the feature branch. - Removed NetCoreServer and the callback/queue forwarding implementation. Native .NET 8 sockets now use two asynchronous pumps, full-send loops, TCP backpressure, TCP_NODELAY/keepalive, and pooled 64 KiB buffers. - Backend setup has a ten-second timeout, observes early client closure, buffers at most 64 KiB before rejecting, and writes the complete trusted SessionInfo record before buffered/client payload. - One atomic two-session IP limiter is shared across playfield listeners only. A separate atomic 2,048-connection process ceiling covers all listeners. Every failure/shutdown path releases admission. - SIGTERM/SIGINT gracefully stop listeners and active sessions. Listener reuse supports prompt restart. The systemd unit adds memory/task/fd ceilings and further sandboxing; offline exposure score improved from 6.6 MEDIUM to 2.8 OK. - Added CI and ten tests covering limiter contention/normalization, cross-listener policy, ordering with queued payload, 2 MiB byte-exact bidirectional forwarding, deterministic backend timeout, early-close cancellation, pre-connect overflow, shutdown cleanup, and aggregate admission. - Strict Release build has zero warnings; 10 tests passed in 20 repeated local runs and in an exact .NET 8 SDK container; self-contained linux-x64 publish passed; NuGet vulnerability scans were clean; final feature review found no actionable issues. Pull request: #6 https://git.project-rk.com/prk/proxy-engine/pulls/6 CI follow-up: the initial .NET SDK job container lacked Node, so JavaScript actions could not run. The workflow now uses the Node 22 Bookworm container and installs the .NET 8 SDK with actions/setup-dotnet before restore; the updated container provides both Node and Git and was pushed in commit 9018e09.
Checklist
0 of 0 completeNo checklist items.
- Area
- Project Rubi-Ka
- Project
- engines
- Kind
- Feature
- Task ID
tsk_enhkgtnjk7- Updated