рабочий вариант, но скороть 10 МБит
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user