Readme
This commit is contained in:
157
README.md
Normal file
157
README.md
Normal file
@@ -0,0 +1,157 @@
|
||||
# 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 they’re not IPv4).
|
||||
|
||||
## Build
|
||||
|
||||
Single-file build:
|
||||
|
||||
```bash
|
||||
# Linux static-ish build (recommended)
|
||||
CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o udpgw ./udpgw.go
|
||||
```
|
||||
|
||||
Run help:
|
||||
|
||||
```bash
|
||||
./udpgw -h
|
||||
```
|
||||
|
||||
## Minimal RAM/CPU start command (recommended profile)
|
||||
|
||||
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:
|
||||
|
||||
```bash
|
||||
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 Go’s 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.
|
||||
|
||||
## Recommended profiles
|
||||
|
||||
### 1) Ultra-low memory (many clients, light traffic)
|
||||
|
||||
```bash
|
||||
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)
|
||||
|
||||
```bash
|
||||
./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)
|
||||
|
||||
```bash
|
||||
./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):
|
||||
|
||||
```ini
|
||||
[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
|
||||
```
|
||||
Reference in New Issue
Block a user