Start with packet header parsing

This commit is contained in:
ChillerDragon 2024-06-02 10:58:09 +08:00
parent ad60b3f368
commit 17047eac70
4 changed files with 230 additions and 2 deletions

56
packet.go Normal file
View file

@ -0,0 +1,56 @@
package main
const (
packetFlagControl = 1
packetFlagResend = 2
packetFlagCompression = 4
packetFlagConnless = 8
)
type PacketFlags struct {
connless bool
compression bool
resend bool
control bool
}
type PacketHeader struct {
flags PacketFlags
ack int
numChunks int
token [4]byte
}
func (header *PacketHeader) unpack(packet []byte) {
header.flags.unpack(packet)
header.ack = (int(packet[0]&0x3) << 8) | int(packet[1])
header.numChunks = int(packet[2])
copy(header.token[:], packet[3:7])
}
func (flags *PacketFlags) unpack(packetHeaderRaw []byte) {
flagBits := packetHeaderRaw[0] >> 2
flags.control = (flagBits & packetFlagControl) != 0
flags.resend = (flagBits & packetFlagResend) != 0
flags.compression = (flagBits & packetFlagCompression) != 0
flags.connless = (flagBits & packetFlagConnless) != 0
}
func (flags *PacketFlags) pack() []byte {
data := 0
if flags.control {
data |= packetFlagControl
}
if flags.resend {
data |= packetFlagResend
}
if flags.compression {
data |= packetFlagCompression
}
if flags.connless {
data |= packetFlagConnless
}
return []byte{byte(data)}
}

172
packet_test.go Normal file
View file

@ -0,0 +1,172 @@
package main
import (
"reflect"
"slices"
"testing"
)
// pack
func TestPackFlagsUnset(t *testing.T) {
flags := PacketFlags{
connless: false,
compression: false,
resend: false,
control: false,
}
got := flags.pack()
want := []byte{0b0000}
if !reflect.DeepEqual(got, want) {
t.Errorf("got %v, wanted %v", got, want)
}
}
func TestPackFlagsCompressionSet(t *testing.T) {
flags := PacketFlags{
connless: false,
compression: true,
resend: false,
control: false,
}
got := flags.pack()
want := []byte{0b0100}
if !reflect.DeepEqual(got, want) {
t.Errorf("got %v, wanted %v", got, want)
}
}
func TestPackFlagsAllSet(t *testing.T) {
flags := PacketFlags{
connless: true,
compression: true,
resend: true,
control: true,
}
got := flags.pack()
want := []byte{0b1111}
if !reflect.DeepEqual(got, want) {
t.Errorf("got %v, wanted %v", got, want)
}
}
// unpack
func TestUnpackFlagsAllSet(t *testing.T) {
got := PacketFlags{}
want := PacketFlags{
connless: true,
compression: true,
resend: true,
control: true,
}
got.unpack([]byte{0b00111100})
if !reflect.DeepEqual(got, want) {
t.Errorf("got %v, wanted %v", got, want)
}
}
func TestUnpackFlagsControlSet(t *testing.T) {
got := PacketFlags{}
want := PacketFlags{
connless: false,
compression: false,
resend: false,
control: true,
}
got.unpack([]byte{0b00000100})
if !reflect.DeepEqual(got, want) {
t.Errorf("got %v, wanted %v", got, want)
}
}
func TestUnpackFlagsUnset(t *testing.T) {
got := PacketFlags{}
want := PacketFlags{
connless: false,
compression: false,
resend: false,
control: false,
}
got.unpack([]byte{0b00000000})
if !reflect.DeepEqual(got, want) {
t.Errorf("got %v, wanted %v", got, want)
}
}
// packet header unpack
func TestUnpackCloseWithReason(t *testing.T) {
got := PacketHeader{}
want := PacketHeader{
flags: PacketFlags{
connless: false,
compression: false,
resend: false,
control: true,
},
ack: 10,
numChunks: 0,
token: [4]byte{0xcf, 0x2e, 0xde, 0x1d},
}
got.unpack(slices.Concat([]byte{0x04, 0x0a, 0x00, 0xcf, 0x2e, 0xde, 0x1d, 0x04}, []byte("shutdown"), []byte{0x00}))
if !reflect.DeepEqual(got, want) {
t.Errorf("got %v, wanted %v", got, want)
}
}
func TestUnpackHeaderFlagsControlSet(t *testing.T) {
got := PacketHeader{}
want := PacketHeader{
flags: PacketFlags{
connless: false,
compression: false,
resend: false,
control: true,
},
ack: 0,
numChunks: 0,
token: [4]byte{0xff, 0xff, 0xff, 0xff},
}
got.unpack([]byte{0b00000100, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff})
if !reflect.DeepEqual(got, want) {
t.Errorf("got %v, wanted %v", got, want)
}
}
func TestUnpackHeaderFlagsAllSet(t *testing.T) {
got := PacketHeader{}
want := PacketHeader{
flags: PacketFlags{
connless: true,
compression: true,
resend: true,
control: true,
},
ack: 0,
numChunks: 0,
token: [4]byte{0xff, 0xff, 0xff, 0xff},
}
got.unpack([]byte{0b00111100, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff})
if !reflect.DeepEqual(got, want) {
t.Errorf("got %v, wanted %v", got, want)
}
}

View file

@ -1,4 +1,4 @@
package teeworlds package main
import ( import (
"bufio" "bufio"

View file

@ -1,4 +1,4 @@
package teeworlds package main
import ( import (
"testing" "testing"