mirror of
https://git.numenor-labs.us/dsfx.git
synced 2025-04-29 16:20:34 +00:00
92 lines
2.3 KiB
Go
92 lines
2.3 KiB
Go
|
package dnet
|
||
|
|
||
|
import (
|
||
|
"encoding/binary"
|
||
|
"errors"
|
||
|
"io"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
// MaxFrameSize is the maximum size of a frame. It is set to 65534 bytes,
|
||
|
// which is one byte less than the maximum value of a uint16 (65535).
|
||
|
MaxFrameSize uint16 = 65535
|
||
|
)
|
||
|
|
||
|
// Frame is a Frame that uses a length prefix to frame the data.
|
||
|
type Frame struct {
|
||
|
contents []byte
|
||
|
}
|
||
|
|
||
|
// NewFrame creates a new Frame with a length prefix.
|
||
|
func NewFrame(contents []byte) *Frame {
|
||
|
return &Frame{
|
||
|
contents: contents,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Contents implements Frame.
|
||
|
func (l *Frame) Contents() []byte {
|
||
|
return l.contents
|
||
|
}
|
||
|
|
||
|
// Len implements Frame.
|
||
|
func (l *Frame) Len() uint16 {
|
||
|
return uint16(len(l.contents))
|
||
|
}
|
||
|
|
||
|
// ReadFrom implements Frame.
|
||
|
func (lpf *Frame) ReadFrom(r io.Reader) (int64, error) {
|
||
|
// LPF expects a 2-byte length prefix followed by the contents.
|
||
|
header := make([]byte, 2)
|
||
|
// Read the header (2 bytes) from the reader. io.ReadFull will return an
|
||
|
// error if it doesn't read exactly 2 bytes.
|
||
|
if _, err := io.ReadFull(r, header); err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
|
||
|
// Calculate the length of the payload.
|
||
|
payloadLen := binary.BigEndian.Uint16(header)
|
||
|
|
||
|
// Check if the payload length exceeds the maximum frame size.
|
||
|
if payloadLen >= MaxFrameSize {
|
||
|
return 0, errors.New("payload length exceeds maximum frame size")
|
||
|
}
|
||
|
|
||
|
// Read the payload from the reader.
|
||
|
payload := make([]byte, payloadLen)
|
||
|
if _, err := io.ReadFull(r, payload); err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
|
||
|
// Set the contents of the frame.
|
||
|
lpf.contents = payload
|
||
|
|
||
|
// Calculate the total length of the frame.
|
||
|
return int64(2 + len(payload)), nil
|
||
|
}
|
||
|
|
||
|
// WriteTo implements Frame.
|
||
|
func (l *Frame) WriteTo(w io.Writer) (int64, error) {
|
||
|
// Check if the payload length exceeds the maximum frame size.
|
||
|
if uint16(len(l.contents)) >= MaxFrameSize {
|
||
|
return 0, errors.New("payload length exceeds maximum frame size")
|
||
|
}
|
||
|
|
||
|
// Create a buffer to hold the length prefix and the payload.
|
||
|
lenBuf := make([]byte, 2)
|
||
|
binary.BigEndian.PutUint16(lenBuf, uint16(len(l.contents)))
|
||
|
|
||
|
// Write the header to the buffer.
|
||
|
if _, err := w.Write(lenBuf); err != nil {
|
||
|
return 0, errors.New("failed to write frame header")
|
||
|
}
|
||
|
|
||
|
// Write the payload to the buffer.
|
||
|
if _, err := w.Write(l.contents); err != nil {
|
||
|
return 0, errors.New("failed to write frame payload")
|
||
|
}
|
||
|
|
||
|
// Calculate the total length of the frame.
|
||
|
return int64(2 + len(l.contents)), nil
|
||
|
}
|