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 }