Mult Protocol

This commit is contained in:
2026-08-16 15:22:03 -03:00
parent 96ea761b72
commit 1fb431ccba
17 changed files with 1873 additions and 204 deletions
+55 -27
View File
@@ -13,6 +13,7 @@ import (
"time"
"dragontcp/internal/protocol"
"dragontcp/internal/xorchunk"
)
const maxHeader = 128 * 1024
@@ -251,7 +252,7 @@ func writeHTTPError(conn net.Conn, code int, reason, detail string) {
_, _ = conn.Write(body)
}
func handleLocal(conn net.Conn, serverAddr, token, transport string, tcpBuffer int, chunkOpts chunkClientOptions, slots chan struct{}) {
func handleLocal(conn net.Conn, serverAddr, token, transport string, tcpBuffer int, wires *wireSelector, slots chan struct{}) {
defer func() {
<-slots
_ = conn.Close()
@@ -285,7 +286,7 @@ func handleLocal(conn net.Conn, serverAddr, token, transport string, tcpBuffer i
var remote net.Conn
if transport == "chunk" {
remote, err = openChunkTunnel(serverAddr, token, host, port, chunkOpts)
remote, err = wires.dial(host, port)
} else {
remote, err = openDragonTCPTunnel(serverAddr, token, host, port, transport, tcpBuffer)
}
@@ -327,7 +328,7 @@ func handleLocal(conn net.Conn, serverAddr, token, transport string, tcpBuffer i
var remote net.Conn
if transport == "chunk" {
remote, err = openChunkTunnel(serverAddr, token, host, port, chunkOpts)
remote, err = wires.dial(host, port)
} else {
remote, err = openDragonTCPTunnel(serverAddr, token, host, port, transport, tcpBuffer)
}
@@ -358,27 +359,28 @@ func handleLocal(conn net.Conn, serverAddr, token, transport string, tcpBuffer i
func main() {
var (
listenHost = flag.String("listen-host", "127.0.0.1", "local proxy listen host")
listenPort = flag.Int("listen-port", 8080, "local proxy listen port")
serverHost = flag.String("server-host", "", "remote DragonTCP server host")
serverPort = flag.Int("server-port", 53, "remote DragonTCP server port")
token = flag.String("token", "", "optional shared token")
maxConnections = flag.Int("max-connections", 20000, "max simultaneous proxy connections")
transport = flag.String("transport", "chunk", "transport: chunk (DragonTCP binary adaptive transport)")
tcpBuffer = flag.Int("tcp-buffer", 0, "optional TCP read/write buffer bytes; 0 keeps OS autotuning")
chunkStart = flag.Int("chunk-start", 1048576, "initial adaptive chunk payload bytes")
chunkMin = flag.Int("chunk-min", 32, "minimum adaptive chunk payload bytes")
chunkMax = flag.Int("chunk-max", 1048576, "maximum adaptive chunk payload bytes (up to 1 MiB)")
chunkAdaptive = flag.Bool("chunk-adaptive", true, "automatically shrink on failures and grow after stable success")
chunkSuccesses = flag.Int("chunk-grow-after", 16, "successful data records required before increasing chunk size")
chunkAdaptLog = flag.Bool("chunk-adapt-log", true, "print adaptive chunk size changes")
chunkSizeLegacy = flag.Int("chunk-size", 0, "legacy fixed chunk size; nonzero disables adaptation")
chunkPollers = flag.Int("chunk-pollers", 1, "reserved compatibility setting; binary transport uses one download worker")
chunkConcurrency = flag.Int("chunk-concurrency", 1, "maximum download records per request (1-256)")
chunkConcurrencyMin = flag.Int("chunk-concurrency-min", 1, "minimum download records per request (1-256); equal to --chunk-concurrency pins the depth and disables batch adaptation")
chunkReconnect = flag.Int("chunk-reconnect-every", 0, "force reconnect after N logical requests; 0 = persistent/automatic")
chunkPollDelay = flag.Duration("chunk-poll-delay", 2*time.Millisecond, "delay after an empty chunk poll")
chunkTimeout = flag.Duration("chunk-timeout", 2*time.Second, "per-record transaction timeout before adaptive shrink")
listenHost = flag.String("listen-host", "127.0.0.1", "local proxy listen host")
listenPort = flag.Int("listen-port", 8080, "local proxy listen port")
serverHost = flag.String("server-host", "", "remote DragonTCP server host")
serverPort = flag.Int("server-port", 53, "remote DragonTCP server port")
token = flag.String("token", "", "optional shared token")
maxConnections = flag.Int("max-connections", 20000, "max simultaneous proxy connections")
transport = flag.String("transport", "chunk", "transport: chunk (DragonTCP binary adaptive transport)")
tcpBuffer = flag.Int("tcp-buffer", 0, "optional TCP read/write buffer bytes; 0 keeps OS autotuning")
chunkStart = flag.Int("chunk-start", 1048576, "initial adaptive chunk payload bytes")
chunkMin = flag.Int("chunk-min", 32, "minimum adaptive chunk payload bytes")
chunkMax = flag.Int("chunk-max", 1048576, "maximum adaptive chunk payload bytes (up to 1 MiB)")
chunkAdaptive = flag.Bool("chunk-adaptive", true, "automatically shrink on failures and grow after stable success")
chunkSuccesses = flag.Int("chunk-grow-after", 16, "successful data records required before increasing chunk size")
chunkAdaptLog = flag.Bool("chunk-adapt-log", true, "print adaptive chunk size changes")
chunkSizeLegacy = flag.Int("chunk-size", 0, "legacy fixed chunk size; nonzero disables adaptation")
chunkPollers = flag.Int("chunk-pollers", 1, "reserved compatibility setting; binary transport uses one download worker")
chunkConcurrency = flag.Int("chunk-concurrency", 1, "maximum download records per request (1-256)")
chunkConcurrencyMin = flag.Int("chunk-concurrency-min", 1, "minimum download records per request (1-256); equal to --chunk-concurrency pins the depth")
chunkReconnect = flag.Int("chunk-reconnect-every", 0, "force reconnect after N logical requests; 0 = persistent/automatic")
chunkPollDelay = flag.Duration("chunk-poll-delay", 2*time.Millisecond, "delay after an empty chunk poll")
chunkTimeout = flag.Duration("chunk-timeout", 2*time.Second, "per-record transaction timeout before adaptive shrink")
wireMode = flag.String("wire", "auto", "wire mode: b, x, or auto (probe and pick)")
)
flag.Parse()
@@ -426,6 +428,17 @@ func main() {
fmt.Fprintln(os.Stderr, "--chunk-concurrency-min must not exceed --chunk-concurrency")
os.Exit(2)
}
*wireMode = strings.ToLower(strings.TrimSpace(*wireMode))
switch *wireMode {
case WireBinary, WireXOR, WireAuto:
case "binary":
*wireMode = WireBinary
case "xor":
*wireMode = WireXOR
default:
fmt.Fprintln(os.Stderr, "--wire must be b, x or auto")
os.Exit(2)
}
if *chunkReconnect < 0 {
fmt.Fprintln(os.Stderr, "--chunk-reconnect-every must be 0 or greater")
os.Exit(2)
@@ -438,14 +451,19 @@ func main() {
adaptSuccesses: *chunkSuccesses,
adaptLog: *chunkAdaptLog,
pollers: *chunkPollers,
minPipeline: *chunkConcurrencyMin,
maxPipeline: *chunkConcurrency,
reconnectEvery: *chunkReconnect,
pollDelay: *chunkPollDelay,
txnTimeout: *chunkTimeout,
tcpBuffer: *tcpBuffer,
minPipeline: *chunkConcurrencyMin,
maxPipeline: *chunkConcurrency,
}
xorOpts := xorchunk.NewOptions(
*chunkStart, *chunkMin, *chunkMax, *chunkAdaptive, *chunkSuccesses, *chunkAdaptLog,
*chunkPollers, *chunkReconnect, *chunkPollDelay, *chunkTimeout, *tcpBuffer,
)
listenAddr := net.JoinHostPort(*listenHost, strconv.Itoa(*listenPort))
serverAddr := net.JoinHostPort(*serverHost, strconv.Itoa(*serverPort))
@@ -480,6 +498,16 @@ func main() {
)
}
wires := newWireSelector(*wireMode, serverAddr, *token, chunkOpts, xorOpts)
if *wireMode == WireAuto {
fmt.Printf("wire=auto probing %s\n", probeHost)
// Resolve in the background so startup is not blocked; a connection that
// arrives first simply waits for the same result.
go wires.mode()
} else {
fmt.Printf("wire=%s (manual)\n", *wireMode)
}
slots := make(chan struct{}, *maxConnections)
for {
@@ -491,7 +519,7 @@ func main() {
select {
case slots <- struct{}{}:
go handleLocal(conn, serverAddr, *token, *transport, *tcpBuffer, chunkOpts, slots)
go handleLocal(conn, serverAddr, *token, *transport, *tcpBuffer, wires, slots)
default:
writeHTTPError(
conn,