go-q3net/header.go

65 lines
1.1 KiB
Go

package quake
import (
"bytes"
"encoding/binary"
)
const (
FRAGMENT_BIT = uint32(1) << 31
MAX_MSGSEQNUM = ^FRAGMENT_BIT
)
var (
endianness = binary.LittleEndian
OOBHeader = &Header{
Fragmented: true,
MessageSequenceNumber: MAX_MSGSEQNUM,
}
)
type Header struct {
Fragmented bool
MessageSequenceNumber uint32
}
func (h *Header) IsOOB() bool {
return h.Fragmented && h.MessageSequenceNumber == MAX_MSGSEQNUM
}
func (h *Header) Marshal() []byte {
// Fragmented is first bit
// Message sequence number is the last 31 bits
finalHeader := h.MessageSequenceNumber
if h.Fragmented {
finalHeader |= FRAGMENT_BIT
}
buf := new(bytes.Buffer)
binary.Write(buf, endianness, finalHeader)
bytes := buf.Bytes()
return bytes
}
func UnmarshalHeader(data []byte) (*Header, error) {
if len(data) < 4 {
return nil, ErrCorruptedMessage
}
// Sequence number
seqNum := endianness.Uint32(data)
// First bit = Fragmented?
fragmented := seqNum&FRAGMENT_BIT != 0
if fragmented {
seqNum &= ^FRAGMENT_BIT
}
return &Header{
Fragmented: fragmented,
MessageSequenceNumber: seqNum,
}, nil
}