From 0d0dbedbcdd25c5a64a71fa1133ffc9892d5251f Mon Sep 17 00:00:00 2001 From: onyx-and-iris Date: Sat, 14 Feb 2026 20:40:38 +0000 Subject: [PATCH] used fixed-sized array for streamname instead of slice. factory method now validates streamname size. framecounter now stored as uint32. it's written to a byte buffer on each call to {Packet}.header() add comment regarding framecounter wraparound. --- packet.go | 54 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/packet.go b/packet.go index d335d0a..6f0879a 100644 --- a/packet.go +++ b/packet.go @@ -3,6 +3,7 @@ package vbantxt import ( "bytes" "encoding/binary" + "fmt" "github.com/charmbracelet/log" ) @@ -21,25 +22,39 @@ var BpsOpts = []int{ } type packet struct { - streamname []byte - bpsIndex int - channel int - framecounter []byte + streamname [streamNameSz]byte + bpsIndex uint8 + channel uint8 + framecounter uint32 hbuf *bytes.Buffer } -// newPacket returns a packet struct with default values, framecounter at 0. -func newPacket(streamname string) packet { - streamnameBuf := make([]byte, streamNameSz) - copy(streamnameBuf, streamname) +// newPacket creates a new packet with the given stream name and default values for other fields. +// It validates the stream name length and ensures the default baud rate is present in BpsOpts. +func newPacket(streamname string) (packet, error) { + if len(streamname) > streamNameSz { + return packet{}, fmt.Errorf( + "streamname too long: %d chars, max %d", + len(streamname), + streamNameSz, + ) + } + + var streamnameBuf [streamNameSz]byte + copy(streamnameBuf[:], streamname) + + bpsIndex := indexOf(BpsOpts, 256000) + if bpsIndex == -1 { + return packet{}, fmt.Errorf("default baud rate 256000 not found in BpsOpts") + } return packet{ streamname: streamnameBuf, - bpsIndex: 0, + bpsIndex: uint8(bpsIndex), channel: 0, - framecounter: make([]byte, 4), - hbuf: bytes.NewBuffer(make([]byte, headerSz)), - } + framecounter: 0, + hbuf: bytes.NewBuffer(make([]byte, 0, headerSz)), + }, nil } // sr defines the samplerate for the request. @@ -60,15 +75,20 @@ func (p *packet) header() []byte { p.hbuf.WriteByte(byte(0)) p.hbuf.WriteByte(p.nbc()) p.hbuf.WriteByte(byte(0x10)) - p.hbuf.Write(p.streamname) - p.hbuf.Write(p.framecounter) + p.hbuf.Write(p.streamname[:]) + + var frameBytes [4]byte + binary.LittleEndian.PutUint32(frameBytes[:], p.framecounter) + p.hbuf.Write(frameBytes[:]) + return p.hbuf.Bytes() } // bumpFrameCounter increments the frame counter by 1. +// The uint32 will safely wrap to 0 after reaching max value (4,294,967,295), +// which is expected behaviour for network protocol sequence numbers. func (p *packet) bumpFrameCounter() { - x := binary.LittleEndian.Uint32(p.framecounter) - binary.LittleEndian.PutUint32(p.framecounter, x+1) + p.framecounter++ - log.Debugf("framecounter: %d", x) + log.Debugf("framecounter: %d", p.framecounter) }