2025-12-12 14:32:09 -03:00
2025-12-12 14:32:09 -03:00

UDPGW (NapsterV framing) — udpgw.go

A lightweight TCP↔UDP gateway that speaks the “NapsterV” UDPGW framing:

  • Listens on TCP (default 0.0.0.0:7400).
  • For each TCP client, opens one UDP socket (stable source port) and forwards framed payloads to UDP targets.
  • Tracks a short-lived mapping so UDP replies are routed back to the correct connID + X byte.
  • IPv4 only (UDP replies are dropped if theyre not IPv4).

Build

Single-file build:

# Linux static-ish build (recommended)
CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o udpgw ./udpgw.go

Run help:

./udpgw -h

This profile is tuned to minimize per-client kernel buffer memory and reduce background CPU (slower map reaping), while keeping behavior safe for most traffic:

GOMAXPROCS=1 ./udpgw   -listen 0.0.0.0:7400   -debug=false   -write-chan 256   -udp-rbuf $((256*1024))   -udp-wbuf $((256*1024))   -map-ttl 60s   -reap-every 30s

Notes:

  • GOMAXPROCS=1 limits Gos scheduler to one OS thread for CPU predictability.
  • -udp-rbuf/-udp-wbuf are the biggest memory knobs because they are applied per TCP client UDP socket.
  • If you see packet loss under load, raise -udp-rbuf/-udp-wbuf to 524288 (512 KiB) or 1048576 (1 MiB) first.

How framing works

Each TCP frame is:

  • LEN (2 bytes, little-endian)
  • PAYLOAD (LEN bytes)

PAYLOAD format for both directions:

  • connID (2 bytes, big-endian)
  • X (1 byte)
  • IPv4 (4 bytes)
  • port (2 bytes, big-endian)
  • data (remaining bytes)

(See readPayload() and buildFrame() in the source.)

Configuration flags

All runtime knobs are flags (defaults shown):

  • -listen 0.0.0.0:7400
    TCP listen address.

  • -max-frame 65536
    Max frame payload length (DoS protection). Frames larger than this are rejected.

  • -debug=false
    Verbose logs.

  • -hexdump 64
    When -debug=true, hex-dump the first N bytes of payload.

  • -write-chan 4096
    TCP write queue depth. Larger can help bursty traffic (e.g., games) but increases worst-case RAM.

  • -udp-bind ""
    Bind the per-client UDP socket to a specific local IP (optional).

  • -udp-rbuf 8388608
    UDP read buffer bytes (socket option). Applied per TCP client.

  • -udp-wbuf 8388608
    UDP write buffer bytes (socket option). Applied per TCP client.

  • -map-ttl 90s
    Destination→connID mapping TTL.

  • -reap-every 10s
    How often to delete expired mappings.

Tuning guide (what affects RAM/CPU the most)

RAM hotspots

  1. Kernel UDP buffers per TCP client
    Roughly proportional to: udp-rbuf + udp-wbuf per connected client.
    Defaults are high (8 MiB + 8 MiB). If you expect many concurrent TCP clients, reduce these.

  2. TCP write queue (-write-chan)
    Each queued element is a []byte frame. Bigger -write-chan allows more buffering but can grow memory.

  3. Per-client TCP reader buffer (fixed)
    The code uses bufio.NewReaderSize(conn, 256*1024) per client (256 KiB). This is not configurable via flags.

CPU hotspots

  1. -debug=true (logging)
    Turn off for production.

  2. Reaper frequency (-reap-every)
    A longer interval reduces wakeups/CPU at the cost of keeping expired mappings a bit longer.

1) Ultra-low memory (many clients, light traffic)

GOMAXPROCS=1 ./udpgw   -listen 0.0.0.0:7400   -write-chan 128   -udp-rbuf $((128*1024))   -udp-wbuf $((128*1024))   -map-ttl 45s   -reap-every 45s

2) Balanced (good default for most servers)

./udpgw   -listen 0.0.0.0:7400   -write-chan 512   -udp-rbuf $((1024*1024))   -udp-wbuf $((1024*1024))   -map-ttl 90s   -reap-every 15s

3) Low-latency / games (avoid drops under bursts)

./udpgw   -listen 0.0.0.0:7400   -write-chan 4096   -udp-rbuf $((4*1024*1024))   -udp-wbuf $((4*1024*1024))   -map-ttl 120s   -reap-every 10s

Operational notes

  • Run behind a firewall; expose only the TCP listen port you need.
  • If you bind -udp-bind, ensure that IP is present on the host.
  • The program will drop UDP replies that are not IPv4.

systemd (optional)

Example unit (adjust paths/flags):

[Unit]
Description=udpgw (NapsterV)
After=network.target

[Service]
Type=simple
WorkingDirectory=/opt/udpgw
Environment=GOMAXPROCS=1
ExecStart=/opt/udpgw/udpgw -listen 0.0.0.0:7400 -write-chan 256 -udp-rbuf 262144 -udp-wbuf 262144 -map-ttl 60s -reap-every 30s
Restart=on-failure
NoNewPrivileges=true
PrivateTmp=true

[Install]
WantedBy=multi-user.target
Description
No description provided
Readme 25 KiB