Start with packet header parsing
This commit is contained in:
parent
ad60b3f368
commit
17047eac70
56
packet.go
Normal file
56
packet.go
Normal 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
172
packet_test.go
Normal 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)
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package teeworlds
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package teeworlds
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
|
Loading…
Reference in a new issue