This commit is contained in:
2026-08-16 13:17:19 -03:00
parent c0a337be3f
commit 7b8e7bfbd0
82 changed files with 5479 additions and 1016 deletions
+211
View File
@@ -0,0 +1,211 @@
package protocol
import (
"encoding/binary"
"errors"
"fmt"
"io"
"net"
"sync"
"time"
)
const (
XORKey byte = 0xAD
// MaxChunkPayload is the hard application-record payload ceiling.
// The adaptive chunk protocol may use any size from 32 bytes through 1 MiB.
MaxChunkPayload = 1024 * 1024
// Framed CPUSH/DATA messages include text metadata in addition to chunk
// bytes, so keep the frame ceiling comfortably above MaxChunkPayload.
MaxHandshake = 2 * 1024 * 1024
)
// 64 KiB balances throughput with memory use at high connection counts.
var BufferPool = sync.Pool{
New: func() any {
b := make([]byte, 64*1024)
return &b
},
}
func ReadRequestFrame(r io.Reader) (uint32, uint32, []byte, error) {
var header [14]byte
if _, err := io.ReadFull(r, header[:]); err != nil {
return 0, 0, nil, err
}
if header[0] != 'U' || header[1] != 'P' {
return 0, 0, nil, errors.New("bad request magic")
}
requestID := binary.BigEndian.Uint32(header[2:6])
reserved := binary.BigEndian.Uint32(header[6:10])
length := binary.BigEndian.Uint32(header[10:14])
if length > MaxHandshake {
return 0, 0, nil, errors.New("handshake payload too large")
}
payload := make([]byte, int(length))
if _, err := io.ReadFull(r, payload); err != nil {
return 0, 0, nil, err
}
XorInPlace(payload)
return requestID, reserved, payload, nil
}
func WriteRequestFrame(w io.Writer, requestID uint32, payload []byte) error {
if len(payload) > MaxHandshake {
return errors.New("request frame payload too large")
}
packet := make([]byte, 14+len(payload))
packet[0], packet[1] = 'U', 'P'
binary.BigEndian.PutUint32(packet[2:6], requestID)
binary.BigEndian.PutUint32(packet[6:10], 0)
binary.BigEndian.PutUint32(packet[10:14], uint32(len(payload)))
copy(packet[14:], payload)
XorInPlace(packet[14:])
return writeAll(w, packet)
}
func ReadResponseFrame(r io.Reader) (uint32, []byte, error) {
var header [10]byte
if _, err := io.ReadFull(r, header[:]); err != nil {
return 0, nil, err
}
if header[0] != 'O' || header[1] != 'K' {
return 0, nil, fmt.Errorf("bad response magic: %q", header[:2])
}
requestID := binary.BigEndian.Uint32(header[2:6])
length := binary.BigEndian.Uint32(header[6:10])
if length > MaxHandshake {
return 0, nil, errors.New("handshake response too large")
}
payload := make([]byte, int(length))
if _, err := io.ReadFull(r, payload); err != nil {
return 0, nil, err
}
XorInPlace(payload)
return requestID, payload, nil
}
func WriteResponseFrame(w io.Writer, requestID uint32, payload []byte) error {
if len(payload) > MaxHandshake {
return errors.New("response frame payload too large")
}
packet := make([]byte, 10+len(payload))
packet[0], packet[1] = 'O', 'K'
binary.BigEndian.PutUint32(packet[2:6], requestID)
binary.BigEndian.PutUint32(packet[6:10], uint32(len(payload)))
copy(packet[10:], payload)
XorInPlace(packet[10:])
return writeAll(w, packet)
}
func writeAll(w io.Writer, b []byte) error {
for len(b) > 0 {
n, err := w.Write(b)
if err != nil {
return err
}
b = b[n:]
}
return nil
}
func CopyXOR(dst net.Conn, src net.Conn) error {
ptr := BufferPool.Get().(*[]byte)
buf := *ptr
defer BufferPool.Put(ptr)
for {
n, err := src.Read(buf)
if n > 0 {
chunk := buf[:n]
XorInPlace(chunk)
if err2 := writeAll(dst, chunk); err2 != nil {
return err2
}
// No restore pass is needed. The next Read overwrites these bytes.
}
if err != nil {
if errors.Is(err, io.EOF) {
return nil
}
return err
}
}
}
func relayPair(a, b net.Conn, copier func(net.Conn, net.Conn) error) {
done := make(chan struct{}, 2)
go func() {
_ = copier(b, a)
if cw, ok := b.(interface{ CloseWrite() error }); ok {
_ = cw.CloseWrite()
}
done <- struct{}{}
}()
go func() {
_ = copier(a, b)
if cw, ok := a.(interface{ CloseWrite() error }); ok {
_ = cw.CloseWrite()
}
done <- struct{}{}
}()
// Preserve normal TCP half-close semantics. The old implementation set a
// 2-second deadline on both connections after the first copy direction
// ended, which truncated slow or large responses. Wait for the remaining
// direction to drain naturally instead.
<-done
<-done
}
func RelayXOR(a, b net.Conn) {
relayPair(a, b, CopyXOR)
}
// RelayRaw allows Go/Linux to use the optimized TCP io.Copy path. On Linux,
// TCP-to-TCP copies can use splice, eliminating the userspace XOR/copy loop.
func RelayRaw(a, b net.Conn) {
relayPair(a, b, func(dst, src net.Conn) error {
_, err := io.Copy(dst, src)
return err
})
}
func TuneTCP(conn net.Conn) {
if tcp, ok := conn.(*net.TCPConn); ok {
_ = tcp.SetNoDelay(true)
_ = tcp.SetKeepAlive(true)
_ = tcp.SetKeepAlivePeriod(30 * time.Second)
}
}
// TuneTCPBuffer optionally requests larger kernel socket buffers. A value <= 0
// leaves Linux/Android autotuning untouched, which is the recommended default
// for large connection counts. For a small number of high-BDP mobile links,
// values such as 1048576 or 4194304 can improve throughput.
func TuneTCPBuffer(conn net.Conn, size int) {
if size <= 0 {
return
}
if tcp, ok := conn.(*net.TCPConn); ok {
_ = tcp.SetReadBuffer(size)
_ = tcp.SetWriteBuffer(size)
}
}
@@ -0,0 +1,44 @@
//go:build arm || 386
package protocol
import "unsafe"
const xorWordMask32 uint32 = 0xADADADAD
// XorInPlace is the 32-bit optimized path used by ARMv7/386 builds.
// It aligns once, then processes 32 bytes per iteration with native uint32
// operations instead of a byte-at-a-time loop.
func XorInPlace(b []byte) {
n := len(b)
if n == 0 {
return
}
i := 0
for i < n && (uintptr(unsafe.Pointer(&b[i]))&3) != 0 {
b[i] ^= XORKey
i++
}
for ; i+32 <= n; i += 32 {
p := unsafe.Pointer(&b[i])
*(*uint32)(unsafe.Add(p, 0)) ^= xorWordMask32
*(*uint32)(unsafe.Add(p, 4)) ^= xorWordMask32
*(*uint32)(unsafe.Add(p, 8)) ^= xorWordMask32
*(*uint32)(unsafe.Add(p, 12)) ^= xorWordMask32
*(*uint32)(unsafe.Add(p, 16)) ^= xorWordMask32
*(*uint32)(unsafe.Add(p, 20)) ^= xorWordMask32
*(*uint32)(unsafe.Add(p, 24)) ^= xorWordMask32
*(*uint32)(unsafe.Add(p, 28)) ^= xorWordMask32
}
for ; i+4 <= n; i += 4 {
p := (*uint32)(unsafe.Pointer(&b[i]))
*p ^= xorWordMask32
}
for ; i < n; i++ {
b[i] ^= XORKey
}
}
@@ -0,0 +1,50 @@
//go:build amd64 || arm64
package protocol
import "unsafe"
const xorWordMask uint64 = 0xADADADADADADADAD
// XorInPlace is optimized for 64-bit targets (amd64/arm64).
//
// It aligns the input once, then XORs 64 bytes per loop iteration using
// eight native 64-bit operations. This removes the encoding/binary call
// overhead from the hot relay path and lets the compiler generate a tight
// load/xor/store loop.
func XorInPlace(b []byte) {
n := len(b)
if n == 0 {
return
}
i := 0
// Align the pointer for native uint64 accesses. This is normally already
// aligned for pooled relay buffers, but also makes this safe for subslices.
for i < n && (uintptr(unsafe.Pointer(&b[i]))&7) != 0 {
b[i] ^= XORKey
i++
}
for ; i+64 <= n; i += 64 {
p := unsafe.Pointer(&b[i])
*(*uint64)(unsafe.Add(p, 0)) ^= xorWordMask
*(*uint64)(unsafe.Add(p, 8)) ^= xorWordMask
*(*uint64)(unsafe.Add(p, 16)) ^= xorWordMask
*(*uint64)(unsafe.Add(p, 24)) ^= xorWordMask
*(*uint64)(unsafe.Add(p, 32)) ^= xorWordMask
*(*uint64)(unsafe.Add(p, 40)) ^= xorWordMask
*(*uint64)(unsafe.Add(p, 48)) ^= xorWordMask
*(*uint64)(unsafe.Add(p, 56)) ^= xorWordMask
}
for ; i+8 <= n; i += 8 {
p := (*uint64)(unsafe.Pointer(&b[i]))
*p ^= xorWordMask
}
for ; i < n; i++ {
b[i] ^= XORKey
}
}
@@ -0,0 +1,10 @@
//go:build !amd64 && !arm64 && !arm && !386
package protocol
// Generic fallback for 32-bit and uncommon architectures.
func XorInPlace(b []byte) {
for i := range b {
b[i] ^= XORKey
}
}
+177
View File
@@ -0,0 +1,177 @@
package wire
import (
"crypto/sha256"
"encoding/binary"
"errors"
"fmt"
"io"
)
const (
RequestHeaderSize = 29
ResponseHeaderSize = 5
MaxPayload = 2 * 1024 * 1024
ModeProbe byte = 0
ModeOpen byte = 1
ModeUpload byte = 2
ModeDownload byte = 3
ModeClose byte = 4
StatusOK byte = 0
StatusError byte = 1
StatusData byte = 2
StatusWait byte = 3
StatusEOF byte = 4
ProbeUpload byte = 1
ProbeDownload byte = 2
ProbeKeepalive byte = 3
ProbeBatch byte = 4
)
var ProbeMagic = [4]byte{'D', 'T', 'P', '2'}
type SessionID [16]byte
type Request struct {
Mode byte
Session SessionID
Seq uint64
Payload []byte
}
func MaskInPlace(data []byte, sid SessionID, mode byte, seq uint64, response bool) {
if len(data) == 0 {
return
}
var seed [30]byte
copy(seed[:16], sid[:])
seed[16] = mode
binary.BigEndian.PutUint64(seed[17:25], seq)
if response {
seed[25] = 1
}
var counter uint32
for off := 0; off < len(data); {
binary.BigEndian.PutUint32(seed[26:30], counter)
block := sha256.Sum256(seed[:])
n := len(data) - off
if n > len(block) {
n = len(block)
}
for i := 0; i < n; i++ {
data[off+i] ^= block[i]
}
off += n
counter++
}
}
func WriteRequest(w io.Writer, mode byte, sid SessionID, seq uint64, plaintext []byte) error {
if len(plaintext) > MaxPayload {
return fmt.Errorf("request payload too large: %d", len(plaintext))
}
packet := make([]byte, RequestHeaderSize+len(plaintext))
packet[0] = mode
copy(packet[1:17], sid[:])
binary.BigEndian.PutUint64(packet[17:25], seq)
binary.BigEndian.PutUint32(packet[25:29], uint32(len(plaintext)))
copy(packet[29:], plaintext)
MaskInPlace(packet[29:], sid, mode, seq, false)
return writeAll(w, packet)
}
func ReadRequest(r io.Reader) (Request, error) {
var req Request
var header [RequestHeaderSize]byte
if _, err := io.ReadFull(r, header[:]); err != nil {
return req, err
}
req.Mode = header[0]
copy(req.Session[:], header[1:17])
req.Seq = binary.BigEndian.Uint64(header[17:25])
n := binary.BigEndian.Uint32(header[25:29])
if n > MaxPayload {
return req, errors.New("request payload too large")
}
if n > 0 {
req.Payload = make([]byte, int(n))
if _, err := io.ReadFull(r, req.Payload); err != nil {
return req, err
}
MaskInPlace(req.Payload, req.Session, req.Mode, req.Seq, false)
}
return req, nil
}
func WriteResponse(w io.Writer, status byte, body []byte) error {
if len(body) > MaxPayload {
return fmt.Errorf("response body too large: %d", len(body))
}
packet := make([]byte, ResponseHeaderSize+len(body))
packet[0] = status
binary.BigEndian.PutUint32(packet[1:5], uint32(len(body)))
copy(packet[5:], body)
return writeAll(w, packet)
}
func WriteMaskedResponse(w io.Writer, status byte, body []byte, sid SessionID, mode byte, seq uint64) error {
if len(body) > MaxPayload {
return fmt.Errorf("response body too large: %d", len(body))
}
packet := make([]byte, ResponseHeaderSize+len(body))
packet[0] = status
binary.BigEndian.PutUint32(packet[1:5], uint32(len(body)))
copy(packet[5:], body)
MaskInPlace(packet[5:], sid, mode, seq, true)
return writeAll(w, packet)
}
func ReadResponse(r io.Reader) (byte, []byte, error) {
var header [ResponseHeaderSize]byte
if _, err := io.ReadFull(r, header[:]); err != nil {
return 0, nil, err
}
n := binary.BigEndian.Uint32(header[1:5])
if n > MaxPayload {
return 0, nil, errors.New("response body too large")
}
var body []byte
if n > 0 {
body = make([]byte, int(n))
if _, err := io.ReadFull(r, body); err != nil {
return 0, nil, err
}
}
return header[0], body, nil
}
func DecodeMaskedResponse(status byte, body []byte, sid SessionID, mode byte, seq uint64) []byte {
if len(body) == 0 || status == StatusError {
return body
}
out := append([]byte(nil), body...)
MaskInPlace(out, sid, mode, seq, true)
return out
}
func writeAll(w io.Writer, b []byte) error {
for len(b) > 0 {
n, err := w.Write(b)
if err != nil {
return err
}
if n <= 0 {
return io.ErrShortWrite
}
b = b[n:]
}
return nil
}
@@ -0,0 +1,29 @@
package wire
import (
"bytes"
"testing"
)
func TestMaskChangesWithSequenceAndRoundTrips(t *testing.T) {
var sid SessionID
for i := range sid { sid[i] = byte(i+1) }
plain := bytes.Repeat([]byte("DragonTCP"), 100)
a := append([]byte(nil), plain...)
b := append([]byte(nil), plain...)
MaskInPlace(a, sid, ModeUpload, 1, false)
MaskInPlace(b, sid, ModeUpload, 2, false)
if bytes.Equal(a, b) { t.Fatal("different sequences produced identical wire bytes") }
MaskInPlace(a, sid, ModeUpload, 1, false)
if !bytes.Equal(a, plain) { t.Fatal("mask did not round-trip") }
}
func BenchmarkMask1MiB(b *testing.B) {
var sid SessionID
data := make([]byte, 1024*1024)
b.SetBytes(int64(len(data)))
b.ResetTimer()
for i:=0;i<b.N;i++ {
MaskInPlace(data,sid,ModeUpload,uint64(i),false)
}
}