mirror of https://github.com/icedream/go-q3net.git
65 lines
1.1 KiB
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
|
|
}
|