Files
rdp-proxy/backend/internal/platform/fabriccontrol/frame.go
T
m 20d361a886
build / backend (push) Has been cancelled
build / node-agent (push) Has been cancelled
build / worker (push) Has been cancelled
рабочий вариант, но скороть 10 МБит
2026-05-22 21:46:49 +03:00

79 lines
1.9 KiB
Go

package fabriccontrol
import (
"encoding/binary"
"errors"
"fmt"
"io"
)
const (
frameMagic uint32 = 0x52415046
frameVersion uint8 = 1
frameHeaderSize = 32
maxPayload = 1024 * 1024
frameData uint8 = 5
trafficClassReliable uint8 = 4
controlForwardQUICStream uint64 = 3
)
type frame struct {
Type uint8
TrafficClass uint8
StreamID uint64
Sequence uint64
Payload []byte
}
var errInvalidFrame = errors.New("invalid fabric frame")
func readFrame(r io.Reader) (frame, error) {
header := make([]byte, frameHeaderSize)
if _, err := io.ReadFull(r, header); err != nil {
return frame{}, err
}
if binary.BigEndian.Uint32(header[0:4]) != frameMagic || header[4] != frameVersion {
return frame{}, errInvalidFrame
}
payloadLen := int(binary.BigEndian.Uint32(header[28:32]))
if payloadLen > maxPayload {
return frame{}, fmt.Errorf("%w: payload too large", errInvalidFrame)
}
out := frame{
Type: header[5],
TrafficClass: header[8],
StreamID: binary.BigEndian.Uint64(header[12:20]),
Sequence: binary.BigEndian.Uint64(header[20:28]),
}
if payloadLen > 0 {
out.Payload = make([]byte, payloadLen)
if _, err := io.ReadFull(r, out.Payload); err != nil {
return frame{}, err
}
}
return out, nil
}
func writeFrame(w io.Writer, f frame) error {
if len(f.Payload) > maxPayload {
return fmt.Errorf("%w: payload too large", errInvalidFrame)
}
header := make([]byte, frameHeaderSize)
binary.BigEndian.PutUint32(header[0:4], frameMagic)
header[4] = frameVersion
header[5] = f.Type
header[8] = f.TrafficClass
binary.BigEndian.PutUint64(header[12:20], f.StreamID)
binary.BigEndian.PutUint64(header[20:28], f.Sequence)
binary.BigEndian.PutUint32(header[28:32], uint32(len(f.Payload)))
if _, err := w.Write(header); err != nil {
return err
}
if len(f.Payload) == 0 {
return nil
}
_, err := w.Write(f.Payload)
return err
}