From 94b6c7787cee2fcee20ce053636089b29393a8ea Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Fri, 21 Jun 2024 13:14:01 +0800 Subject: [PATCH] Keep unkown messages on repack --- messages7/unknown.go | 60 ++++++++++++++++ packer/packer.go | 4 ++ packer/packer_state_test.go | 27 +++++++ protocol7/connection.go | 40 +++++++++-- protocol7/packet.go | 3 + protocol7/packet_test.go | 138 ++++++++++++++++++++++++++++++++++++ 6 files changed, 265 insertions(+), 7 deletions(-) create mode 100644 messages7/unknown.go diff --git a/messages7/unknown.go b/messages7/unknown.go new file mode 100644 index 0000000..acbc49e --- /dev/null +++ b/messages7/unknown.go @@ -0,0 +1,60 @@ +package messages7 + +import ( + "github.com/teeworlds-go/teeworlds/chunk7" + "github.com/teeworlds-go/teeworlds/network7" + "github.com/teeworlds-go/teeworlds/packer" +) + +type Unknown struct { + ChunkHeader *chunk7.ChunkHeader + + // contains entire raw message + // including message id and chunk header + // can either be a control message or a game/system message + Data []byte + Type network7.MsgType +} + +func (msg Unknown) MsgId() int { + msgId := packer.UnpackInt(msg.Data) + if msg.Type == network7.TypeControl { + return msgId + } + msgId >>= 1 + return msgId +} + +func (msg Unknown) MsgType() network7.MsgType { + return msg.Type +} + +func (msg Unknown) System() bool { + msgId := packer.UnpackInt(msg.Data) + if msg.Type == network7.TypeControl { + return false + } + sys := msgId&1 != 0 + return sys +} + +func (msg Unknown) Vital() bool { + // TODO: check is not ctrl and then unpack Data + panic("not implemented yet") +} + +func (msg Unknown) Pack() []byte { + return msg.Data +} + +func (msg *Unknown) Unpack(u *packer.Unpacker) { + msg.Data = u.Rest() +} + +func (msg *Unknown) Header() *chunk7.ChunkHeader { + return nil +} + +func (msg *Unknown) SetHeader(header *chunk7.ChunkHeader) { + msg.ChunkHeader = header +} diff --git a/packer/packer.go b/packer/packer.go index 852d8fa..15973f3 100644 --- a/packer/packer.go +++ b/packer/packer.go @@ -30,6 +30,10 @@ func (u *Unpacker) Data() []byte { return u.data } +func (u *Unpacker) Rest() []byte { + return u.data[u.idx:] +} + const ( Sanitize = 1 SanitizeCC = 2 diff --git a/packer/packer_state_test.go b/packer/packer_state_test.go index 24c9d04..5fc8298 100644 --- a/packer/packer_state_test.go +++ b/packer/packer_state_test.go @@ -5,6 +5,33 @@ import ( "testing" ) +// rest + +func TestUnpackRest(t *testing.T) { + u := Unpacker{} + u.Reset([]byte{0x01, 0xff, 0xaa}) + + { + got := u.GetInt() + want := 1 + + if got != want { + t.Errorf("got %v, wanted %v", got, want) + } + } + + { + got := u.Rest() + want := []byte{0xff, 0xaa} + + if !reflect.DeepEqual(got, want) { + t.Errorf("got %v, wanted %v", got, want) + } + } +} + +// client info + func TestUnpackClientInfo(t *testing.T) { u := Unpacker{} u.Reset([]byte{ diff --git a/protocol7/connection.go b/protocol7/connection.go index 37c45db..ede6658 100644 --- a/protocol7/connection.go +++ b/protocol7/connection.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" "os" + "slices" "github.com/teeworlds-go/huffman" "github.com/teeworlds-go/teeworlds/chunk7" @@ -95,7 +96,7 @@ func byteSliceToString(s []byte) string { return string(s) } -func (connection *Connection) OnSystemMsg(msg int, chunk chunk7.Chunk, u *packer.Unpacker, result *PacketResult) { +func (connection *Connection) OnSystemMsg(msg int, chunk chunk7.Chunk, u *packer.Unpacker, result *PacketResult) bool { if msg == network7.MsgSysMapChange { fmt.Println("got map change") result.Response.Messages = append(result.Response.Messages, &messages7.Ready{}) @@ -108,7 +109,9 @@ func (connection *Connection) OnSystemMsg(msg int, chunk chunk7.Chunk, u *packer result.Response.Messages = append(result.Response.Messages, &messages7.CtrlKeepAlive{}) } else { fmt.Printf("unknown system message id=%d data=%x\n", msg, chunk.Data) + return false } + return true } func (client *Connection) OnChatMessage(msg *messages7.SvChat) { @@ -124,7 +127,7 @@ func (client *Connection) OnMotd(motd string) { fmt.Printf("[motd] %s\n", motd) } -func (client *Connection) OnGameMsg(msg int, chunk chunk7.Chunk, u *packer.Unpacker, result *PacketResult) { +func (client *Connection) OnGameMsg(msg int, chunk chunk7.Chunk, u *packer.Unpacker, result *PacketResult) bool { if msg == network7.MsgGameReadyToEnter { fmt.Println("got ready to enter") result.Packet.Messages = append(result.Packet.Messages, &messages7.Ready{ChunkHeader: &chunk.Header}) @@ -146,10 +149,12 @@ func (client *Connection) OnGameMsg(msg int, chunk chunk7.Chunk, u *packer.Unpac fmt.Printf("got client info id=%d name=%s\n", clientId, client.Players[clientId].Info.Name) } else { fmt.Printf("unknown game message id=%d data=%x\n", msg, chunk.Data) + return false } + return true } -func (client *Connection) OnMessage(chunk chunk7.Chunk, result *PacketResult) { +func (client *Connection) OnMessage(chunk chunk7.Chunk, result *PacketResult) bool { // fmt.Printf("got chunk size=%d data=%v\n", chunk.Header.Size, chunk.Data) if chunk.Header.Flags.Vital { @@ -165,17 +170,22 @@ func (client *Connection) OnMessage(chunk chunk7.Chunk, result *PacketResult) { msg >>= 1 if sys { - client.OnSystemMsg(msg, chunk, &u, result) - } else { - client.OnGameMsg(msg, chunk, &u, result) + return client.OnSystemMsg(msg, chunk, &u, result) } + return client.OnGameMsg(msg, chunk, &u, result) } func (connection *Connection) OnPacketPayload(data []byte, result *PacketResult) (*PacketResult, error) { chunks := chunk7.UnpackChunks(data) for _, c := range chunks { - connection.OnMessage(c, result) + if connection.OnMessage(c, result) == false { + unknown := &messages7.Unknown{ + Data: slices.Concat(c.Header.Pack(), c.Data), + Type: network7.TypeNet, + } + result.Packet.Messages = append(result.Packet.Messages, unknown) + } } return result, nil @@ -190,6 +200,17 @@ type PacketResult struct { Packet *Packet } +// TODO: there should be a Packet.Unpack() +// +// and it should only do the parsing no state handling or responses +// and Connection.OnPack() should take a Packet instance as parameter +// not raw data +// So ideally it would look like this: +// +// packet := Packet{} +// packet.Unpack(data) +// conn := Connection{} +// result, err := conn.OnPacket(packet) func (connection *Connection) OnPacket(data []byte) (*PacketResult, error) { result := &PacketResult{ Response: connection.BuildResponse(), @@ -226,6 +247,11 @@ func (connection *Connection) OnPacket(data []byte) (*PacketResult, error) { os.Exit(0) } else { + unknown := &messages7.Unknown{ + Data: payload, + Type: network7.TypeControl, + } + result.Packet.Messages = append(result.Packet.Messages, unknown) fmt.Printf("unknown control message: %x\n", data) } diff --git a/protocol7/packet.go b/protocol7/packet.go index 138d405..fd0dbb0 100644 --- a/protocol7/packet.go +++ b/protocol7/packet.go @@ -40,6 +40,9 @@ type Packet struct { } func PackChunk(msg messages7.NetMessage, connection *Connection) []byte { + if _, ok := msg.(*messages7.Unknown); ok { + return msg.Pack() + } if msg.MsgType() == network7.TypeControl { return msg.Pack() } diff --git a/protocol7/packet_test.go b/protocol7/packet_test.go index 76979dc..405bad4 100644 --- a/protocol7/packet_test.go +++ b/protocol7/packet_test.go @@ -9,6 +9,144 @@ import ( "github.com/teeworlds-go/teeworlds/messages7" ) +// repack packet with unknown messages should not lose data + +func TestRepackUnknownMessages(t *testing.T) { + // TODO: once 9e220138-d393-3cb0-90f1-e587c00ab1d0 + // is supported this test makes no sense anymore + // because if the entire ddnet protocol is implemeted this dump does + // not contain an unknown message anymore + // to fix this add a custom unused uuid ddnet msg and or a unused teeworlds msg id + + // libtw2 dissector dump of ddnet7 connecting to official ddnet server + // Teeworlds 0.7 Protocol packet + // Teeworlds 0.7 Protocol chunk: game.sv_chat + // Teeworlds 0.7 Protocol chunk: game.sv_chat + // Teeworlds 0.7 Protocol chunk: game.sv_game_info + // Teeworlds 0.7 Protocol chunk: game.sv_command_info_remove + // Teeworlds 0.7 Protocol chunk: game.9e220138-d393-3cb0-90f1-e587c00ab1d0 + // Teeworlds 0.7 Protocol chunk: game.sv_command_info + // Teeworlds 0.7 Protocol chunk: game.sv_command_info + // Teeworlds 0.7 Protocol chunk: game.sv_command_info + // Teeworlds 0.7 Protocol chunk: game.sv_command_info + // Teeworlds 0.7 Protocol chunk: game.sv_command_info + // Teeworlds 0.7 Protocol chunk: game.sv_command_info + // Teeworlds 0.7 Protocol chunk: game.sv_command_info + // Teeworlds 0.7 Protocol chunk: game.sv_command_info + // Teeworlds 0.7 Protocol chunk: game.sv_command_info + // Teeworlds 0.7 Protocol chunk: game.sv_command_info + // Teeworlds 0.7 Protocol chunk: game.sv_command_info + // Teeworlds 0.7 Protocol chunk: game.sv_command_info + // Teeworlds 0.7 Protocol chunk: game.sv_command_info + // Teeworlds 0.7 Protocol chunk: game.sv_command_info + // Teeworlds 0.7 Protocol chunk: game.sv_command_info + // Teeworlds 0.7 Protocol chunk: game.sv_command_info + // Teeworlds 0.7 Protocol chunk: game.sv_command_info + + dump := []byte{ + 0x00, 0x05, 0x16, 0x8d, 0x5b, 0x17, 0x48, 0x40, 0x2c, 0x24, 0x06, 0x01, 0x40, 0x40, 0x44, 0x44, + 0x72, 0x61, 0x63, 0x65, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x4d, 0x6f, 0x64, 0x2e, + 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x30, 0x2e, 0x36, 0x2e, 0x34, 0x2c, + 0x20, 0x31, 0x38, 0x2e, 0x33, 0x00, 0x41, 0x09, 0x25, 0x06, 0x01, 0x40, 0x40, 0x70, 0x6c, 0x65, + 0x61, 0x73, 0x65, 0x20, 0x76, 0x69, 0x73, 0x69, 0x74, 0x20, 0x44, 0x44, 0x4e, 0x65, 0x74, 0x2e, + 0x6f, 0x72, 0x67, 0x20, 0x6f, 0x72, 0x20, 0x73, 0x61, 0x79, 0x20, 0x2f, 0x69, 0x6e, 0x66, 0x6f, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, + 0x6f, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x2f, 0x72, 0x75, 0x6c, 0x65, + 0x73, 0x00, 0x40, 0x06, 0x26, 0x26, 0x08, 0x00, 0x00, 0x00, 0x01, 0x40, 0x07, 0x27, 0x8c, 0x01, + 0x74, 0x65, 0x61, 0x6d, 0x00, 0x40, 0x11, 0x28, 0x00, 0x9e, 0x22, 0x01, 0x38, 0xd3, 0x93, 0x3c, + 0xb0, 0x90, 0xf1, 0xe5, 0x87, 0xc0, 0x0a, 0xb1, 0xd0, 0x42, 0x07, 0x29, 0x8a, 0x01, 0x61, 0x64, + 0x64, 0x77, 0x65, 0x61, 0x70, 0x6f, 0x6e, 0x00, 0x69, 0x5b, 0x77, 0x65, 0x61, 0x70, 0x6f, 0x6e, + 0x2d, 0x69, 0x64, 0x5d, 0x00, 0x47, 0x69, 0x76, 0x65, 0x73, 0x20, 0x77, 0x65, 0x61, 0x70, 0x6f, + 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x69, 0x64, 0x20, 0x69, 0x20, 0x74, 0x6f, 0x20, 0x79, + 0x6f, 0x75, 0x20, 0x28, 0x61, 0x6c, 0x6c, 0x20, 0x3d, 0x20, 0x2d, 0x31, 0x2c, 0x20, 0x68, 0x61, + 0x6d, 0x6d, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x20, 0x67, 0x75, 0x6e, 0x20, 0x3d, 0x20, + 0x31, 0x2c, 0x20, 0x73, 0x68, 0x6f, 0x74, 0x67, 0x75, 0x6e, 0x20, 0x3d, 0x20, 0x32, 0x2c, 0x20, + 0x67, 0x72, 0x65, 0x6e, 0x61, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x33, 0x2c, 0x20, 0x6c, 0x61, 0x73, + 0x65, 0x72, 0x20, 0x3d, 0x20, 0x34, 0x2c, 0x20, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x20, 0x3d, 0x20, + 0x35, 0x29, 0x00, 0x41, 0x10, 0x2a, 0x8a, 0x01, 0x63, 0x00, 0x72, 0x5b, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x5d, 0x00, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x70, 0x65, 0x72, 0x73, + 0x6f, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x77, 0x68, 0x69, 0x73, 0x70, 0x65, 0x72, 0x65, 0x64, + 0x20, 0x74, 0x6f, 0x20, 0x28, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x29, 0x00, 0x40, 0x3c, 0x2b, 0x8a, 0x01, 0x63, 0x6d, 0x64, 0x6c, 0x69, + 0x73, 0x74, 0x00, 0x00, 0x4c, 0x69, 0x73, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, 0x72, 0x65, 0x20, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x75, + 0x73, 0x65, 0x72, 0x73, 0x00, 0x41, 0x17, 0x2c, 0x8a, 0x01, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, + 0x73, 0x65, 0x00, 0x72, 0x5b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5d, 0x00, 0x43, 0x6f, + 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x6c, 0x61, 0x73, 0x74, 0x20, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x20, + 0x77, 0x68, 0x69, 0x73, 0x70, 0x65, 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x28, 0x70, 0x72, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x29, 0x00, 0x40, + 0x2e, 0x2d, 0x8a, 0x01, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x73, 0x00, 0x00, 0x53, 0x68, 0x6f, + 0x77, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x73, 0x20, 0x6f, + 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x44, 0x44, 0x4e, 0x65, 0x74, 0x20, 0x6d, 0x6f, 0x64, 0x00, + 0x40, 0x22, 0x2e, 0x8a, 0x01, 0x64, 0x65, 0x65, 0x70, 0x00, 0x00, 0x50, 0x75, 0x74, 0x73, 0x20, + 0x79, 0x6f, 0x75, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x64, 0x65, 0x65, 0x70, 0x20, 0x66, 0x72, + 0x65, 0x65, 0x7a, 0x65, 0x00, 0x40, 0x3b, 0x2f, 0x8a, 0x01, 0x64, 0x6e, 0x64, 0x00, 0x00, 0x54, + 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x20, 0x44, 0x6f, 0x20, 0x4e, 0x6f, 0x74, 0x20, 0x44, 0x69, 0x73, + 0x74, 0x75, 0x72, 0x62, 0x20, 0x28, 0x6e, 0x6f, 0x20, 0x63, 0x68, 0x61, 0x74, 0x20, 0x61, 0x6e, + 0x64, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x73, 0x29, 0x00, 0x41, 0x08, 0x30, 0x8a, 0x01, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x00, 0x3f, 0x73, + 0x5b, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x5d, 0x20, 0x69, 0x5b, 0x64, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, + 0x64, 0x73, 0x5d, 0x00, 0x53, 0x65, 0x74, 0x73, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x74, 0x65, + 0x65, 0x27, 0x73, 0x20, 0x65, 0x79, 0x65, 0x20, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x00, 0x42, 0x31, + 0x31, 0x8a, 0x01, 0x65, 0x79, 0x65, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x00, 0x3f, 0x73, 0x5b, 0x27, + 0x6f, 0x6e, 0x27, 0x7c, 0x27, 0x6f, 0x66, 0x66, 0x27, 0x7c, 0x27, 0x74, 0x6f, 0x67, 0x67, 0x6c, + 0x65, 0x27, 0x5d, 0x00, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x73, 0x20, 0x75, 0x73, 0x65, 0x20, + 0x6f, 0x66, 0x20, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x65, 0x79, 0x65, 0x2d, + 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x73, 0x20, 0x6f, 0x6e, 0x2f, 0x6f, 0x66, 0x66, 0x2c, 0x20, 0x65, + 0x79, 0x65, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x20, 0x73, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, + 0x20, 0x73, 0x20, 0x3d, 0x20, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6f, 0x6e, 0x2c, 0x20, + 0x6f, 0x66, 0x66, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6f, 0x66, 0x66, 0x2c, 0x20, 0x74, 0x6f, 0x67, + 0x67, 0x6c, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x68, + 0x6f, 0x77, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x00, 0x40, 0x2b, 0x32, 0x8a, 0x01, 0x67, 0x72, 0x65, 0x6e, 0x61, 0x64, 0x65, 0x00, 0x00, + 0x47, 0x69, 0x76, 0x65, 0x73, 0x20, 0x61, 0x20, 0x67, 0x72, 0x65, 0x6e, 0x61, 0x64, 0x65, 0x20, + 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x79, 0x6f, 0x75, 0x00, + 0x41, 0x07, 0x33, 0x8a, 0x01, 0x68, 0x65, 0x6c, 0x70, 0x00, 0x3f, 0x72, 0x5b, 0x63, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x5d, 0x00, 0x53, 0x68, 0x6f, 0x77, 0x73, 0x20, 0x68, 0x65, 0x6c, 0x70, + 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x2c, 0x20, 0x67, + 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x68, 0x65, 0x6c, 0x70, 0x20, 0x69, 0x66, 0x20, 0x6c, + 0x65, 0x66, 0x74, 0x20, 0x62, 0x6c, 0x61, 0x6e, 0x6b, 0x00, 0x40, 0x25, 0x34, 0x8a, 0x01, 0x69, + 0x6e, 0x66, 0x6f, 0x00, 0x00, 0x53, 0x68, 0x6f, 0x77, 0x73, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x20, + 0x61, 0x62, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x00, 0x40, 0x39, 0x35, 0x8a, 0x01, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x00, 0x72, 0x5b, + 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x5d, 0x00, 0x49, 0x6e, 0x76, + 0x69, 0x74, 0x65, 0x20, 0x61, 0x20, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, + 0x61, 0x20, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x20, 0x74, 0x65, 0x61, 0x6d, 0x00, 0x40, 0x20, + 0x36, 0x8a, 0x01, 0x6a, 0x65, 0x74, 0x70, 0x61, 0x63, 0x6b, 0x00, 0x00, 0x47, 0x69, 0x76, 0x65, + 0x73, 0x20, 0x6a, 0x65, 0x74, 0x70, 0x61, 0x63, 0x6b, 0x20, 0x74, 0x6f, 0x20, 0x79, 0x6f, 0x75, + 0x00, 0x40, 0x3c, 0x37, 0x8a, 0x01, 0x6a, 0x6f, 0x69, 0x6e, 0x00, 0x72, 0x5b, 0x70, 0x6c, 0x61, + 0x79, 0x65, 0x72, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x5d, 0x00, 0x4a, 0x6f, 0x69, 0x6e, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x74, 0x65, 0x61, 0x6d, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, + 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x00, + 0x41, 0x1d, 0x38, 0x8a, 0x01, 0x6b, 0x69, 0x6c, 0x6c, 0x00, 0x00, 0x4b, 0x69, 0x6c, 0x6c, 0x20, + 0x79, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x6c, 0x66, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x6b, 0x69, + 0x6c, 0x6c, 0x2d, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x64, 0x75, 0x72, + 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x67, 0x61, 0x6d, 0x65, 0x20, + 0x28, 0x75, 0x73, 0x65, 0x20, 0x66, 0x31, 0x2c, 0x20, 0x6b, 0x69, 0x6c, 0x6c, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x72, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x20, 0x6b, 0x69, 0x6c, 0x6c, 0x29, 0x00, + 0x40, 0x1e, 0x39, 0x8a, 0x01, 0x6c, 0x61, 0x73, 0x65, 0x72, 0x00, 0x00, 0x47, 0x69, 0x76, 0x65, + 0x73, 0x20, 0x61, 0x20, 0x6c, 0x61, 0x73, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x79, 0x6f, 0x75, + 0x00, + } + + conn := Connection{} + result, err := conn.OnPacket(dump) + if err != nil { + t.Errorf("Unexpected error %v\n", err) + } + + repack := result.Packet.Pack(&conn) + + if !reflect.DeepEqual(repack, dump) { + t.Errorf("got %v, wanted %v", repack, dump) + } +} + // update chunk headers func TestPackUpdateChunkHeaders(t *testing.T) {