Make packet a module and import huffman
This commit is contained in:
parent
17047eac70
commit
4d307dc990
28
.github/workflows/main.yml
vendored
Normal file
28
.github/workflows/main.yml
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
name: Go
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.22'
|
||||
|
||||
- name: Build
|
||||
run: go build -v ./...
|
||||
|
||||
- name: Test
|
||||
run: go test -v ./...
|
||||
|
||||
- name: Format
|
||||
run: diff -u <(echo -n) <(gofmt -d ./)
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1 +1,3 @@
|
|||
teeworlds_client
|
||||
teeworlds
|
||||
|
||||
|
|
2
go.mod
2
go.mod
|
@ -1,3 +1,5 @@
|
|||
module github.com/teeworlds-go/teeworlds
|
||||
|
||||
go 1.22.3
|
||||
|
||||
require github.com/teeworlds-go/huffman v1.0.0 // indirect
|
||||
|
|
2
go.sum
Normal file
2
go.sum
Normal file
|
@ -0,0 +1,2 @@
|
|||
github.com/teeworlds-go/huffman v1.0.0 h1:XSNMNAJZb+njNrPACsxcDrrLDXTGjZZt35FqLAuHi4I=
|
||||
github.com/teeworlds-go/huffman v1.0.0/go.mod h1:kjaXpL6C6xL7CM+tWPNYjdEgVZB2GumKhx7rCDdXArU=
|
56
packet.go
56
packet.go
|
@ -1,56 +0,0 @@
|
|||
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)}
|
||||
}
|
56
packet/packet.go
Normal file
56
packet/packet.go
Normal file
|
@ -0,0 +1,56 @@
|
|||
package packet
|
||||
|
||||
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)}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package packet
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
@ -10,13 +10,13 @@ import (
|
|||
|
||||
func TestPackFlagsUnset(t *testing.T) {
|
||||
flags := PacketFlags{
|
||||
connless: false,
|
||||
compression: false,
|
||||
resend: false,
|
||||
control: false,
|
||||
Connless: false,
|
||||
Compression: false,
|
||||
Resend: false,
|
||||
Control: false,
|
||||
}
|
||||
|
||||
got := flags.pack()
|
||||
got := flags.Pack()
|
||||
want := []byte{0b0000}
|
||||
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
|
@ -26,13 +26,13 @@ func TestPackFlagsUnset(t *testing.T) {
|
|||
|
||||
func TestPackFlagsCompressionSet(t *testing.T) {
|
||||
flags := PacketFlags{
|
||||
connless: false,
|
||||
compression: true,
|
||||
resend: false,
|
||||
control: false,
|
||||
Connless: false,
|
||||
Compression: true,
|
||||
Resend: false,
|
||||
Control: false,
|
||||
}
|
||||
|
||||
got := flags.pack()
|
||||
got := flags.Pack()
|
||||
want := []byte{0b0100}
|
||||
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
|
@ -42,13 +42,13 @@ func TestPackFlagsCompressionSet(t *testing.T) {
|
|||
|
||||
func TestPackFlagsAllSet(t *testing.T) {
|
||||
flags := PacketFlags{
|
||||
connless: true,
|
||||
compression: true,
|
||||
resend: true,
|
||||
control: true,
|
||||
Connless: true,
|
||||
Compression: true,
|
||||
Resend: true,
|
||||
Control: true,
|
||||
}
|
||||
|
||||
got := flags.pack()
|
||||
got := flags.Pack()
|
||||
want := []byte{0b1111}
|
||||
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
|
@ -61,13 +61,13 @@ func TestPackFlagsAllSet(t *testing.T) {
|
|||
func TestUnpackFlagsAllSet(t *testing.T) {
|
||||
got := PacketFlags{}
|
||||
want := PacketFlags{
|
||||
connless: true,
|
||||
compression: true,
|
||||
resend: true,
|
||||
control: true,
|
||||
Connless: true,
|
||||
Compression: true,
|
||||
Resend: true,
|
||||
Control: true,
|
||||
}
|
||||
|
||||
got.unpack([]byte{0b00111100})
|
||||
got.Unpack([]byte{0b00111100})
|
||||
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("got %v, wanted %v", got, want)
|
||||
|
@ -77,13 +77,13 @@ func TestUnpackFlagsAllSet(t *testing.T) {
|
|||
func TestUnpackFlagsControlSet(t *testing.T) {
|
||||
got := PacketFlags{}
|
||||
want := PacketFlags{
|
||||
connless: false,
|
||||
compression: false,
|
||||
resend: false,
|
||||
control: true,
|
||||
Connless: false,
|
||||
Compression: false,
|
||||
Resend: false,
|
||||
Control: true,
|
||||
}
|
||||
|
||||
got.unpack([]byte{0b00000100})
|
||||
got.Unpack([]byte{0b00000100})
|
||||
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("got %v, wanted %v", got, want)
|
||||
|
@ -93,13 +93,13 @@ func TestUnpackFlagsControlSet(t *testing.T) {
|
|||
func TestUnpackFlagsUnset(t *testing.T) {
|
||||
got := PacketFlags{}
|
||||
want := PacketFlags{
|
||||
connless: false,
|
||||
compression: false,
|
||||
resend: false,
|
||||
control: false,
|
||||
Connless: false,
|
||||
Compression: false,
|
||||
Resend: false,
|
||||
Control: false,
|
||||
}
|
||||
|
||||
got.unpack([]byte{0b00000000})
|
||||
got.Unpack([]byte{0b00000000})
|
||||
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("got %v, wanted %v", got, want)
|
||||
|
@ -111,18 +111,18 @@ func TestUnpackFlagsUnset(t *testing.T) {
|
|||
func TestUnpackCloseWithReason(t *testing.T) {
|
||||
got := PacketHeader{}
|
||||
want := PacketHeader{
|
||||
flags: PacketFlags{
|
||||
connless: false,
|
||||
compression: false,
|
||||
resend: false,
|
||||
control: true,
|
||||
Flags: PacketFlags{
|
||||
Connless: false,
|
||||
Compression: false,
|
||||
Resend: false,
|
||||
Control: true,
|
||||
},
|
||||
ack: 10,
|
||||
numChunks: 0,
|
||||
token: [4]byte{0xcf, 0x2e, 0xde, 0x1d},
|
||||
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}))
|
||||
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)
|
||||
|
@ -132,18 +132,18 @@ func TestUnpackCloseWithReason(t *testing.T) {
|
|||
func TestUnpackHeaderFlagsControlSet(t *testing.T) {
|
||||
got := PacketHeader{}
|
||||
want := PacketHeader{
|
||||
flags: PacketFlags{
|
||||
connless: false,
|
||||
compression: false,
|
||||
resend: false,
|
||||
control: true,
|
||||
Flags: PacketFlags{
|
||||
Connless: false,
|
||||
Compression: false,
|
||||
Resend: false,
|
||||
Control: true,
|
||||
},
|
||||
ack: 0,
|
||||
numChunks: 0,
|
||||
token: [4]byte{0xff, 0xff, 0xff, 0xff},
|
||||
Ack: 0,
|
||||
NumChunks: 0,
|
||||
Token: [4]byte{0xff, 0xff, 0xff, 0xff},
|
||||
}
|
||||
|
||||
got.unpack([]byte{0b00000100, 0x00, 0x00, 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)
|
||||
|
@ -153,18 +153,18 @@ func TestUnpackHeaderFlagsControlSet(t *testing.T) {
|
|||
func TestUnpackHeaderFlagsAllSet(t *testing.T) {
|
||||
got := PacketHeader{}
|
||||
want := PacketHeader{
|
||||
flags: PacketFlags{
|
||||
connless: true,
|
||||
compression: true,
|
||||
resend: true,
|
||||
control: true,
|
||||
Flags: PacketFlags{
|
||||
Connless: true,
|
||||
Compression: true,
|
||||
Resend: true,
|
||||
Control: true,
|
||||
},
|
||||
ack: 0,
|
||||
numChunks: 0,
|
||||
token: [4]byte{0xff, 0xff, 0xff, 0xff},
|
||||
Ack: 0,
|
||||
NumChunks: 0,
|
||||
Token: [4]byte{0xff, 0xff, 0xff, 0xff},
|
||||
}
|
||||
|
||||
got.unpack([]byte{0b00111100, 0x00, 0x00, 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)
|
19
teeworlds.go
19
teeworlds.go
|
@ -8,6 +8,9 @@ import (
|
|||
"os"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"github.com/teeworlds-go/huffman"
|
||||
"github.com/teeworlds-go/teeworlds/packet"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -160,7 +163,10 @@ func byteSliceToString(s []byte) string {
|
|||
}
|
||||
|
||||
func (client *TeeworldsClient) onMessage(data []byte) {
|
||||
if isCtrlMsg(data) {
|
||||
header := packet.PacketHeader{}
|
||||
header.Unpack(data)
|
||||
|
||||
if header.Flags.Control {
|
||||
ctrlMsg := data[7]
|
||||
fmt.Printf("got ctrl msg %d\n", ctrlMsg)
|
||||
if ctrlMsg == msgCtrlToken {
|
||||
|
@ -181,10 +187,19 @@ func (client *TeeworldsClient) onMessage(data []byte) {
|
|||
} else {
|
||||
fmt.Printf("unknown control message: %x\n", data)
|
||||
}
|
||||
} else if header.Flags.Compression {
|
||||
payload := data[8:]
|
||||
fmt.Printf("got compressed data: %v\n", payload)
|
||||
huff := huffman.Huffman{}
|
||||
decompressed, err := huff.Decompress(payload)
|
||||
if err != nil {
|
||||
fmt.Printf("huffman error: %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("got decompressed: %v\n", decompressed)
|
||||
} else if isMapChange(data) {
|
||||
fmt.Println("got map change")
|
||||
client.sendReady()
|
||||
|
||||
} else if isConReady(data) {
|
||||
fmt.Println("got ready")
|
||||
client.sendStartInfo()
|
||||
|
|
Loading…
Reference in a new issue