diff --git a/chunk7/splitter.go b/chunk7/splitter.go index 686a46f..6e51edb 100644 --- a/chunk7/splitter.go +++ b/chunk7/splitter.go @@ -18,7 +18,7 @@ func UnpackChunks(data []byte) []Chunk { } end := i + chunk.Header.Size chunk.Data = make([]byte, end-i) - copy(chunk.Data[:], data[i:end]) + copy(chunk.Data, data[i:end]) i += chunk.Header.Size chunks = append(chunks, chunk) } diff --git a/go.mod b/go.mod index 2d98f07..05ac4c2 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,4 @@ module github.com/teeworlds-go/go-teeworlds-protocol go 1.22.3 -require github.com/teeworlds-go/huffman v1.0.0 // indirect +require github.com/teeworlds-go/huffman v1.0.0 diff --git a/internal/testutils/require/require.go b/internal/testutils/require/require.go new file mode 100644 index 0000000..71b76a1 --- /dev/null +++ b/internal/testutils/require/require.go @@ -0,0 +1,53 @@ +package require + +import ( + "reflect" + "testing" +) + +func New(t *testing.T) *Require { + return &Require{ + t: t, + } +} + +type Require struct { + t *testing.T +} + +func (r *Require) Equal(expected any, actual any) { + r.t.Helper() + Equal(r.t, expected, actual) +} + +func (r *Require) NoError(err error) { + r.t.Helper() + NoError(r.t, err) +} + +func (r *Require) NotNil(a any) { + r.t.Helper() + NotNil(r.t, a) +} + +func Equal(t *testing.T, expected any, actual any) { + t.Helper() + if !reflect.DeepEqual(expected, actual) { + t.Fatalf("expected: %v, got: %v", expected, actual) + } +} + +func NoError(t *testing.T, err error) { + t.Helper() + if err != nil { + t.Fatalf("expected no error, got: %v", err) + } +} + +func NotNil(t *testing.T, a any) { + t.Helper() + if a != nil { + return + } + t.Fatalf("expected not nil, got: %v", a) +} diff --git a/internal/testutils/testutils.go b/internal/testutils/testutils.go new file mode 100644 index 0000000..95c4dc9 --- /dev/null +++ b/internal/testutils/testutils.go @@ -0,0 +1 @@ +package testutils diff --git a/messages7/auth_challenge.go b/messages7/auth_challenge.go index 396d073..f10d7f8 100644 --- a/messages7/auth_challenge.go +++ b/messages7/auth_challenge.go @@ -11,27 +11,28 @@ type AuthChallenge struct { ChunkHeader *chunk7.ChunkHeader } -func (msg AuthChallenge) MsgId() int { +func (msg *AuthChallenge) MsgId() int { return network7.MsgSysAuthChallenge } -func (msg AuthChallenge) MsgType() network7.MsgType { +func (msg *AuthChallenge) MsgType() network7.MsgType { return network7.TypeNet } -func (msg AuthChallenge) System() bool { +func (msg *AuthChallenge) System() bool { return true } -func (msg AuthChallenge) Vital() bool { +func (msg *AuthChallenge) Vital() bool { return true } -func (msg AuthChallenge) Pack() []byte { +func (msg *AuthChallenge) Pack() []byte { return []byte{} } -func (msg *AuthChallenge) Unpack(u *packer.Unpacker) { +func (msg *AuthChallenge) Unpack(u *packer.Unpacker) error { + return nil } func (msg *AuthChallenge) Header() *chunk7.ChunkHeader { diff --git a/messages7/auth_response.go b/messages7/auth_response.go index 1ed1ea1..29d03a7 100644 --- a/messages7/auth_response.go +++ b/messages7/auth_response.go @@ -11,27 +11,28 @@ type AuthResponse struct { ChunkHeader *chunk7.ChunkHeader } -func (msg AuthResponse) MsgId() int { +func (msg *AuthResponse) MsgId() int { return network7.MsgSysAuthResponse } -func (msg AuthResponse) MsgType() network7.MsgType { +func (msg *AuthResponse) MsgType() network7.MsgType { return network7.TypeNet } -func (msg AuthResponse) System() bool { +func (msg *AuthResponse) System() bool { return true } -func (msg AuthResponse) Vital() bool { +func (msg *AuthResponse) Vital() bool { return true } -func (msg AuthResponse) Pack() []byte { +func (msg *AuthResponse) Pack() []byte { return []byte{} } -func (msg *AuthResponse) Unpack(u *packer.Unpacker) { +func (msg *AuthResponse) Unpack(u *packer.Unpacker) error { + return nil } func (msg *AuthResponse) Header() *chunk7.ChunkHeader { diff --git a/messages7/auth_result.go b/messages7/auth_result.go index e4d25b1..b8e5ae3 100644 --- a/messages7/auth_result.go +++ b/messages7/auth_result.go @@ -11,27 +11,28 @@ type AuthResult struct { ChunkHeader *chunk7.ChunkHeader } -func (msg AuthResult) MsgId() int { +func (msg *AuthResult) MsgId() int { return network7.MsgSysAuthResult } -func (msg AuthResult) MsgType() network7.MsgType { +func (msg *AuthResult) MsgType() network7.MsgType { return network7.TypeNet } -func (msg AuthResult) System() bool { +func (msg *AuthResult) System() bool { return true } -func (msg AuthResult) Vital() bool { +func (msg *AuthResult) Vital() bool { return true } -func (msg AuthResult) Pack() []byte { +func (msg *AuthResult) Pack() []byte { return []byte{} } -func (msg *AuthResult) Unpack(u *packer.Unpacker) { +func (msg *AuthResult) Unpack(u *packer.Unpacker) error { + return nil } func (msg *AuthResult) Header() *chunk7.ChunkHeader { diff --git a/messages7/auth_start.go b/messages7/auth_start.go index 2cba389..687d237 100644 --- a/messages7/auth_start.go +++ b/messages7/auth_start.go @@ -11,27 +11,28 @@ type AuthStart struct { ChunkHeader *chunk7.ChunkHeader } -func (msg AuthStart) MsgId() int { +func (msg *AuthStart) MsgId() int { return network7.MsgSysAuthStart } -func (msg AuthStart) MsgType() network7.MsgType { +func (msg *AuthStart) MsgType() network7.MsgType { return network7.TypeNet } -func (msg AuthStart) System() bool { +func (msg *AuthStart) System() bool { return true } -func (msg AuthStart) Vital() bool { +func (msg *AuthStart) Vital() bool { return true } -func (msg AuthStart) Pack() []byte { +func (msg *AuthStart) Pack() []byte { return []byte{} } -func (msg *AuthStart) Unpack(u *packer.Unpacker) { +func (msg *AuthStart) Unpack(u *packer.Unpacker) error { + return nil } func (msg *AuthStart) Header() *chunk7.ChunkHeader { diff --git a/messages7/cl_start_info.go b/messages7/cl_start_info.go index a969f6c..6044b4d 100644 --- a/messages7/cl_start_info.go +++ b/messages7/cl_start_info.go @@ -34,70 +34,71 @@ type ClStartInfo struct { ColorEyes int } -func (info ClStartInfo) MsgId() int { +func (msg *ClStartInfo) MsgId() int { return network7.MsgGameClStartInfo } -func (info ClStartInfo) MsgType() network7.MsgType { +func (msg *ClStartInfo) MsgType() network7.MsgType { return network7.TypeNet } -func (info ClStartInfo) System() bool { +func (msg *ClStartInfo) System() bool { return false } -func (info ClStartInfo) Vital() bool { +func (msg *ClStartInfo) Vital() bool { return true } -func (info ClStartInfo) Pack() []byte { +func (msg *ClStartInfo) Pack() []byte { return slices.Concat( - packer.PackStr(info.Name), - packer.PackStr(info.Clan), - packer.PackInt(info.Country), - packer.PackStr(info.Body), - packer.PackStr(info.Marking), - packer.PackStr(info.Decoration), - packer.PackStr(info.Hands), - packer.PackStr(info.Feet), - packer.PackStr(info.Eyes), - packer.PackBool(info.CustomColorBody), - packer.PackBool(info.CustomColorMarking), - packer.PackBool(info.CustomColorDecoration), - packer.PackBool(info.CustomColorHands), - packer.PackBool(info.CustomColorFeet), - packer.PackBool(info.CustomColorEyes), - packer.PackInt(info.ColorBody), - packer.PackInt(info.ColorMarking), - packer.PackInt(info.ColorDecoration), - packer.PackInt(info.ColorHands), - packer.PackInt(info.ColorFeet), - packer.PackInt(info.ColorEyes), + packer.PackStr(msg.Name), + packer.PackStr(msg.Clan), + packer.PackInt(msg.Country), + packer.PackStr(msg.Body), + packer.PackStr(msg.Marking), + packer.PackStr(msg.Decoration), + packer.PackStr(msg.Hands), + packer.PackStr(msg.Feet), + packer.PackStr(msg.Eyes), + packer.PackBool(msg.CustomColorBody), + packer.PackBool(msg.CustomColorMarking), + packer.PackBool(msg.CustomColorDecoration), + packer.PackBool(msg.CustomColorHands), + packer.PackBool(msg.CustomColorFeet), + packer.PackBool(msg.CustomColorEyes), + packer.PackInt(msg.ColorBody), + packer.PackInt(msg.ColorMarking), + packer.PackInt(msg.ColorDecoration), + packer.PackInt(msg.ColorHands), + packer.PackInt(msg.ColorFeet), + packer.PackInt(msg.ColorEyes), ) } -func (info *ClStartInfo) Unpack(u *packer.Unpacker) { - info.Name = u.GetString() - info.Clan = u.GetString() - info.Country = u.GetInt() - info.Body = u.GetString() - info.Marking = u.GetString() - info.Decoration = u.GetString() - info.Hands = u.GetString() - info.Feet = u.GetString() - info.Eyes = u.GetString() - info.CustomColorBody = u.GetInt() != 0 - info.CustomColorMarking = u.GetInt() != 0 - info.CustomColorDecoration = u.GetInt() != 0 - info.CustomColorHands = u.GetInt() != 0 - info.CustomColorFeet = u.GetInt() != 0 - info.CustomColorEyes = u.GetInt() != 0 - info.ColorBody = u.GetInt() - info.ColorMarking = u.GetInt() - info.ColorDecoration = u.GetInt() - info.ColorHands = u.GetInt() - info.ColorFeet = u.GetInt() - info.ColorEyes = u.GetInt() +func (msg *ClStartInfo) Unpack(u *packer.Unpacker) error { + msg.Name = u.GetString() + msg.Clan = u.GetString() + msg.Country = u.GetInt() + msg.Body = u.GetString() + msg.Marking = u.GetString() + msg.Decoration = u.GetString() + msg.Hands = u.GetString() + msg.Feet = u.GetString() + msg.Eyes = u.GetString() + msg.CustomColorBody = u.GetInt() != 0 + msg.CustomColorMarking = u.GetInt() != 0 + msg.CustomColorDecoration = u.GetInt() != 0 + msg.CustomColorHands = u.GetInt() != 0 + msg.CustomColorFeet = u.GetInt() != 0 + msg.CustomColorEyes = u.GetInt() != 0 + msg.ColorBody = u.GetInt() + msg.ColorMarking = u.GetInt() + msg.ColorDecoration = u.GetInt() + msg.ColorHands = u.GetInt() + msg.ColorFeet = u.GetInt() + msg.ColorEyes = u.GetInt() + return nil } func (msg *ClStartInfo) Header() *chunk7.ChunkHeader { diff --git a/messages7/cl_start_info_test.go b/messages7/cl_start_info_test.go index 9e348d7..231c985 100644 --- a/messages7/cl_start_info_test.go +++ b/messages7/cl_start_info_test.go @@ -1,9 +1,9 @@ package messages7 import ( - "reflect" "testing" + "github.com/teeworlds-go/go-teeworlds-protocol/internal/testutils/require" "github.com/teeworlds-go/go-teeworlds-protocol/packer" ) @@ -44,10 +44,7 @@ func TestPackStartInfo(t *testing.T) { } got := info.Pack() - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + require.Equal(t, got, want) } func TestUnpackStartInfo(t *testing.T) { @@ -64,34 +61,29 @@ func TestUnpackStartInfo(t *testing.T) { }) info := ClStartInfo{} - info.Unpack(&u) + err := info.Unpack(&u) + require.NoError(t, err) { - got := info.Eyes want := "standard" - if got != want { - t.Errorf("got %v, wanted %v", got, want) - } + got := info.Eyes + require.Equal(t, got, want) - got = info.Decoration want = "" + got = info.Decoration if got != want { t.Errorf("got %v, wanted %v", got, want) } - got = info.Marking want = "duodonny" - if got != want { - t.Errorf("got %v, wanted %v", got, want) - } + got = info.Marking + require.Equal(t, got, want) } { - got := info.ColorDecoration want := 65408 - if got != want { - t.Errorf("got %v, wanted %v", got, want) - } + got := info.ColorDecoration + require.Equal(t, got, want) } wantedInfo := ClStartInfo{ @@ -118,7 +110,5 @@ func TestUnpackStartInfo(t *testing.T) { ColorEyes: 65408, } - if !reflect.DeepEqual(info, wantedInfo) { - t.Errorf("got %v, wanted %v", info, wantedInfo) - } + require.Equal(t, wantedInfo, info) } diff --git a/messages7/con_ready.go b/messages7/con_ready.go index 25fc521..86e636c 100644 --- a/messages7/con_ready.go +++ b/messages7/con_ready.go @@ -10,27 +10,28 @@ type ConReady struct { ChunkHeader *chunk7.ChunkHeader } -func (msg ConReady) MsgId() int { +func (msg *ConReady) MsgId() int { return network7.MsgSysConReady } -func (msg ConReady) MsgType() network7.MsgType { +func (msg *ConReady) MsgType() network7.MsgType { return network7.TypeNet } -func (msg ConReady) System() bool { +func (msg *ConReady) System() bool { return true } -func (msg ConReady) Vital() bool { +func (msg *ConReady) Vital() bool { return true } -func (msg ConReady) Pack() []byte { +func (msg *ConReady) Pack() []byte { return []byte{} } -func (msg *ConReady) Unpack(u *packer.Unpacker) { +func (msg *ConReady) Unpack(u *packer.Unpacker) error { + return nil } func (msg *ConReady) Header() *chunk7.ChunkHeader { diff --git a/messages7/ctrl_accept.go b/messages7/ctrl_accept.go index 8c081e9..9d85c29 100644 --- a/messages7/ctrl_accept.go +++ b/messages7/ctrl_accept.go @@ -12,23 +12,23 @@ type CtrlAccept struct { Token [4]byte } -func (msg CtrlAccept) MsgId() int { +func (msg *CtrlAccept) MsgId() int { return network7.MsgCtrlAccept } -func (msg CtrlAccept) MsgType() network7.MsgType { +func (msg *CtrlAccept) MsgType() network7.MsgType { return network7.TypeControl } -func (msg CtrlAccept) System() bool { +func (msg *CtrlAccept) System() bool { return false } -func (msg CtrlAccept) Vital() bool { +func (msg *CtrlAccept) Vital() bool { return false } -func (msg CtrlAccept) Pack() []byte { +func (msg *CtrlAccept) Pack() []byte { return slices.Concat( []byte{network7.MsgCtrlAccept}, msg.Token[:], @@ -36,7 +36,8 @@ func (msg CtrlAccept) Pack() []byte { ) } -func (msg *CtrlAccept) Unpack(u *packer.Unpacker) { +func (msg *CtrlAccept) Unpack(u *packer.Unpacker) error { + return nil } func (msg *CtrlAccept) Header() *chunk7.ChunkHeader { diff --git a/messages7/ctrl_close.go b/messages7/ctrl_close.go index 3c0aed1..9f7fe52 100644 --- a/messages7/ctrl_close.go +++ b/messages7/ctrl_close.go @@ -12,32 +12,33 @@ type CtrlClose struct { Reason string } -func (msg CtrlClose) MsgId() int { +func (msg *CtrlClose) MsgId() int { return network7.MsgCtrlClose } -func (msg CtrlClose) MsgType() network7.MsgType { +func (msg *CtrlClose) MsgType() network7.MsgType { return network7.TypeControl } -func (msg CtrlClose) System() bool { +func (msg *CtrlClose) System() bool { return false } -func (msg CtrlClose) Vital() bool { +func (msg *CtrlClose) Vital() bool { return false } -func (msg CtrlClose) Pack() []byte { +func (msg *CtrlClose) Pack() []byte { return slices.Concat( []byte{network7.MsgCtrlClose}, packer.PackStr(msg.Reason), ) } -func (msg *CtrlClose) Unpack(u *packer.Unpacker) { +func (msg *CtrlClose) Unpack(u *packer.Unpacker) error { // TODO: sanitize msg.Reason = u.GetString() + return nil } func (msg *CtrlClose) Header() *chunk7.ChunkHeader { diff --git a/messages7/ctrl_connect.go b/messages7/ctrl_connect.go index b02a0e2..6e2e86a 100644 --- a/messages7/ctrl_connect.go +++ b/messages7/ctrl_connect.go @@ -12,23 +12,23 @@ type CtrlConnect struct { Token [4]byte } -func (msg CtrlConnect) MsgId() int { +func (msg *CtrlConnect) MsgId() int { return network7.MsgCtrlConnect } -func (msg CtrlConnect) MsgType() network7.MsgType { +func (msg *CtrlConnect) MsgType() network7.MsgType { return network7.TypeControl } -func (msg CtrlConnect) System() bool { +func (msg *CtrlConnect) System() bool { return false } -func (msg CtrlConnect) Vital() bool { +func (msg *CtrlConnect) Vital() bool { return false } -func (msg CtrlConnect) Pack() []byte { +func (msg *CtrlConnect) Pack() []byte { return slices.Concat( []byte{network7.MsgCtrlConnect}, msg.Token[:], @@ -36,8 +36,9 @@ func (msg CtrlConnect) Pack() []byte { ) } -func (msg *CtrlConnect) Unpack(u *packer.Unpacker) { +func (msg *CtrlConnect) Unpack(u *packer.Unpacker) error { msg.Token = [4]byte(u.Rest()) + return nil } func (msg *CtrlConnect) Header() *chunk7.ChunkHeader { diff --git a/messages7/ctrl_keep_alive.go b/messages7/ctrl_keep_alive.go index 3f2d292..c2c1041 100644 --- a/messages7/ctrl_keep_alive.go +++ b/messages7/ctrl_keep_alive.go @@ -9,27 +9,28 @@ import ( type CtrlKeepAlive struct { } -func (msg CtrlKeepAlive) MsgId() int { +func (msg *CtrlKeepAlive) MsgId() int { return network7.MsgCtrlKeepAlive } -func (msg CtrlKeepAlive) MsgType() network7.MsgType { +func (msg *CtrlKeepAlive) MsgType() network7.MsgType { return network7.TypeControl } -func (msg CtrlKeepAlive) System() bool { +func (msg *CtrlKeepAlive) System() bool { return false } -func (msg CtrlKeepAlive) Vital() bool { +func (msg *CtrlKeepAlive) Vital() bool { return false } -func (msg CtrlKeepAlive) Pack() []byte { +func (msg *CtrlKeepAlive) Pack() []byte { return []byte{network7.MsgCtrlKeepAlive} } -func (msg *CtrlKeepAlive) Unpack(u *packer.Unpacker) { +func (msg *CtrlKeepAlive) Unpack(u *packer.Unpacker) error { + return nil } func (msg *CtrlKeepAlive) Header() *chunk7.ChunkHeader { diff --git a/messages7/ctrl_token.go b/messages7/ctrl_token.go index 7321918..5c4222e 100644 --- a/messages7/ctrl_token.go +++ b/messages7/ctrl_token.go @@ -15,23 +15,23 @@ type CtrlToken struct { Token [4]byte } -func (msg CtrlToken) MsgId() int { +func (msg *CtrlToken) MsgId() int { return network7.MsgCtrlToken } -func (msg CtrlToken) MsgType() network7.MsgType { +func (msg *CtrlToken) MsgType() network7.MsgType { return network7.TypeControl } -func (msg CtrlToken) System() bool { +func (msg *CtrlToken) System() bool { return false } -func (msg CtrlToken) Vital() bool { +func (msg *CtrlToken) Vital() bool { return false } -func (msg CtrlToken) Pack() []byte { +func (msg *CtrlToken) Pack() []byte { return slices.Concat( []byte{network7.MsgCtrlToken}, msg.Token[:], @@ -39,8 +39,9 @@ func (msg CtrlToken) Pack() []byte { ) } -func (msg *CtrlToken) Unpack(u *packer.Unpacker) { +func (msg *CtrlToken) Unpack(u *packer.Unpacker) error { msg.Token = [4]byte(u.Rest()) + return nil } func (msg *CtrlToken) Header() *chunk7.ChunkHeader { diff --git a/messages7/enter_game.go b/messages7/enter_game.go index 145c5e2..68ad5bb 100644 --- a/messages7/enter_game.go +++ b/messages7/enter_game.go @@ -10,27 +10,28 @@ type EnterGame struct { ChunkHeader *chunk7.ChunkHeader } -func (msg EnterGame) MsgId() int { +func (msg *EnterGame) MsgId() int { return network7.MsgSysEnterGame } -func (msg EnterGame) MsgType() network7.MsgType { +func (msg *EnterGame) MsgType() network7.MsgType { return network7.TypeNet } -func (msg EnterGame) System() bool { +func (msg *EnterGame) System() bool { return true } -func (msg EnterGame) Vital() bool { +func (msg *EnterGame) Vital() bool { return true } -func (msg EnterGame) Pack() []byte { +func (msg *EnterGame) Pack() []byte { return []byte{} } -func (msg *EnterGame) Unpack(u *packer.Unpacker) { +func (msg *EnterGame) Unpack(u *packer.Unpacker) error { + return nil } func (msg *EnterGame) Header() *chunk7.ChunkHeader { diff --git a/messages7/error.go b/messages7/error.go index 2d056d4..05df4f5 100644 --- a/messages7/error.go +++ b/messages7/error.go @@ -11,27 +11,28 @@ type Error struct { ChunkHeader *chunk7.ChunkHeader } -func (msg Error) MsgId() int { +func (msg *Error) MsgId() int { return network7.MsgSysError } -func (msg Error) MsgType() network7.MsgType { +func (msg *Error) MsgType() network7.MsgType { return network7.TypeNet } -func (msg Error) System() bool { +func (msg *Error) System() bool { return true } -func (msg Error) Vital() bool { +func (msg *Error) Vital() bool { return true } -func (msg Error) Pack() []byte { +func (msg *Error) Pack() []byte { return []byte{} } -func (msg *Error) Unpack(u *packer.Unpacker) { +func (msg *Error) Unpack(u *packer.Unpacker) error { + return nil } func (msg *Error) Header() *chunk7.ChunkHeader { diff --git a/messages7/info.go b/messages7/info.go index be5ea85..5abe827 100644 --- a/messages7/info.go +++ b/messages7/info.go @@ -34,7 +34,7 @@ type Info struct { ClientVersion int } -func (msg Info) MsgId() int { +func (msg *Info) MsgId() int { return network7.MsgSysInfo } @@ -42,15 +42,15 @@ func (info Info) MsgType() network7.MsgType { return network7.TypeNet } -func (msg Info) System() bool { +func (msg *Info) System() bool { return true } -func (msg Info) Vital() bool { +func (msg *Info) Vital() bool { return true } -func (msg Info) Pack() []byte { +func (msg *Info) Pack() []byte { return slices.Concat( packer.PackStr(msg.Version), packer.PackStr(msg.Password), @@ -58,10 +58,11 @@ func (msg Info) Pack() []byte { ) } -func (msg *Info) Unpack(u *packer.Unpacker) { +func (msg *Info) Unpack(u *packer.Unpacker) error { msg.Version = u.GetString() msg.Password = u.GetString() msg.ClientVersion = u.GetInt() + return nil } func (msg *Info) Header() *chunk7.ChunkHeader { diff --git a/messages7/input.go b/messages7/input.go index 1749f3a..551eccb 100644 --- a/messages7/input.go +++ b/messages7/input.go @@ -27,23 +27,23 @@ type Input struct { PrevWeapon network7.Weapon } -func (msg Input) MsgId() int { +func (msg *Input) MsgId() int { return network7.MsgSysInput } -func (msg Input) MsgType() network7.MsgType { +func (msg *Input) MsgType() network7.MsgType { return network7.TypeNet } -func (msg Input) System() bool { +func (msg *Input) System() bool { return true } -func (msg Input) Vital() bool { +func (msg *Input) Vital() bool { return false } -func (msg Input) Pack() []byte { +func (msg *Input) Pack() []byte { return slices.Concat( packer.PackInt(msg.Direction), packer.PackInt(msg.TargetX), @@ -58,7 +58,7 @@ func (msg Input) Pack() []byte { ) } -func (msg *Input) Unpack(u *packer.Unpacker) { +func (msg *Input) Unpack(u *packer.Unpacker) error { msg.Direction = u.GetInt() msg.TargetX = u.GetInt() msg.TargetY = u.GetInt() @@ -69,6 +69,7 @@ func (msg *Input) Unpack(u *packer.Unpacker) { msg.WantedWeapon = network7.Weapon(u.GetInt()) msg.NextWeapon = network7.Weapon(u.GetInt()) msg.PrevWeapon = network7.Weapon(u.GetInt()) + return nil } func (msg *Input) Header() *chunk7.ChunkHeader { diff --git a/messages7/input_timing.go b/messages7/input_timing.go index 7a5c25b..f7a3884 100644 --- a/messages7/input_timing.go +++ b/messages7/input_timing.go @@ -15,32 +15,33 @@ type InputTiming struct { TimeLeft int } -func (msg InputTiming) MsgId() int { +func (msg *InputTiming) MsgId() int { return network7.MsgSysInputTiming } -func (msg InputTiming) MsgType() network7.MsgType { +func (msg *InputTiming) MsgType() network7.MsgType { return network7.TypeNet } -func (msg InputTiming) System() bool { +func (msg *InputTiming) System() bool { return true } -func (msg InputTiming) Vital() bool { +func (msg *InputTiming) Vital() bool { return false } -func (msg InputTiming) Pack() []byte { +func (msg *InputTiming) Pack() []byte { return slices.Concat( packer.PackInt(msg.IntendedPredTick), packer.PackInt(msg.TimeLeft), ) } -func (msg *InputTiming) Unpack(u *packer.Unpacker) { +func (msg *InputTiming) Unpack(u *packer.Unpacker) error { msg.IntendedPredTick = u.GetInt() msg.TimeLeft = u.GetInt() + return nil } func (msg *InputTiming) Header() *chunk7.ChunkHeader { diff --git a/messages7/map_change.go b/messages7/map_change.go index a042501..21caecb 100644 --- a/messages7/map_change.go +++ b/messages7/map_change.go @@ -19,23 +19,23 @@ type MapChange struct { Sha256 [32]byte } -func (msg MapChange) MsgId() int { +func (msg *MapChange) MsgId() int { return network7.MsgSysMapChange } -func (msg MapChange) MsgType() network7.MsgType { +func (msg *MapChange) MsgType() network7.MsgType { return network7.TypeNet } -func (msg MapChange) System() bool { +func (msg *MapChange) System() bool { return true } -func (msg MapChange) Vital() bool { +func (msg *MapChange) Vital() bool { return true } -func (msg MapChange) Pack() []byte { +func (msg *MapChange) Pack() []byte { return slices.Concat( packer.PackStr(msg.Name), packer.PackInt(msg.Crc), @@ -46,13 +46,14 @@ func (msg MapChange) Pack() []byte { ) } -func (msg *MapChange) Unpack(u *packer.Unpacker) { +func (msg *MapChange) Unpack(u *packer.Unpacker) error { msg.Name = u.GetString() msg.Crc = u.GetInt() msg.Size = u.GetInt() msg.NumResponseChunksPerRequest = u.GetInt() msg.ChunkSize = u.GetInt() msg.Sha256 = [32]byte(u.Rest()) + return nil } func (msg *MapChange) Header() *chunk7.ChunkHeader { diff --git a/messages7/map_data.go b/messages7/map_data.go index baa3f6a..0da3d34 100644 --- a/messages7/map_data.go +++ b/messages7/map_data.go @@ -12,28 +12,29 @@ type MapData struct { Data []byte } -func (msg MapData) MsgId() int { +func (msg *MapData) MsgId() int { return network7.MsgSysMapData } -func (msg MapData) MsgType() network7.MsgType { +func (msg *MapData) MsgType() network7.MsgType { return network7.TypeNet } -func (msg MapData) System() bool { +func (msg *MapData) System() bool { return true } -func (msg MapData) Vital() bool { +func (msg *MapData) Vital() bool { return true } -func (msg MapData) Pack() []byte { +func (msg *MapData) Pack() []byte { return msg.Data } -func (msg *MapData) Unpack(u *packer.Unpacker) { +func (msg *MapData) Unpack(u *packer.Unpacker) error { msg.Data = u.Rest() + return nil } func (msg *MapData) Header() *chunk7.ChunkHeader { diff --git a/messages7/maplist_entry_add.go b/messages7/maplist_entry_add.go index 311b385..03a57e8 100644 --- a/messages7/maplist_entry_add.go +++ b/messages7/maplist_entry_add.go @@ -14,30 +14,31 @@ type MaplistEntryAdd struct { MapName string } -func (msg MaplistEntryAdd) MsgId() int { +func (msg *MaplistEntryAdd) MsgId() int { return network7.MsgSysMaplistEntryAdd } -func (msg MaplistEntryAdd) MsgType() network7.MsgType { +func (msg *MaplistEntryAdd) MsgType() network7.MsgType { return network7.TypeNet } -func (msg MaplistEntryAdd) System() bool { +func (msg *MaplistEntryAdd) System() bool { return true } -func (msg MaplistEntryAdd) Vital() bool { +func (msg *MaplistEntryAdd) Vital() bool { return true } -func (msg MaplistEntryAdd) Pack() []byte { +func (msg *MaplistEntryAdd) Pack() []byte { return slices.Concat( packer.PackStr(msg.MapName), ) } -func (msg *MaplistEntryAdd) Unpack(u *packer.Unpacker) { +func (msg *MaplistEntryAdd) Unpack(u *packer.Unpacker) error { msg.MapName = u.GetString() + return nil } func (msg *MaplistEntryAdd) Header() *chunk7.ChunkHeader { diff --git a/messages7/maplist_entry_rem.go b/messages7/maplist_entry_rem.go index 22df6f1..bd12ff7 100644 --- a/messages7/maplist_entry_rem.go +++ b/messages7/maplist_entry_rem.go @@ -14,30 +14,31 @@ type MaplistEntryRem struct { MapName string } -func (msg MaplistEntryRem) MsgId() int { +func (msg *MaplistEntryRem) MsgId() int { return network7.MsgSysMaplistEntryRem } -func (msg MaplistEntryRem) MsgType() network7.MsgType { +func (msg *MaplistEntryRem) MsgType() network7.MsgType { return network7.TypeNet } -func (msg MaplistEntryRem) System() bool { +func (msg *MaplistEntryRem) System() bool { return true } -func (msg MaplistEntryRem) Vital() bool { +func (msg *MaplistEntryRem) Vital() bool { return true } -func (msg MaplistEntryRem) Pack() []byte { +func (msg *MaplistEntryRem) Pack() []byte { return slices.Concat( packer.PackStr(msg.MapName), ) } -func (msg *MaplistEntryRem) Unpack(u *packer.Unpacker) { +func (msg *MaplistEntryRem) Unpack(u *packer.Unpacker) error { msg.MapName = u.GetString() + return nil } func (msg *MaplistEntryRem) Header() *chunk7.ChunkHeader { diff --git a/messages7/net_message.go b/messages7/net_message.go index 72dd974..69220e7 100644 --- a/messages7/net_message.go +++ b/messages7/net_message.go @@ -12,7 +12,7 @@ type NetMessage interface { System() bool Vital() bool Pack() []byte - Unpack(u *packer.Unpacker) + Unpack(u *packer.Unpacker) error Header() *chunk7.ChunkHeader SetHeader(header *chunk7.ChunkHeader) diff --git a/messages7/ping.go b/messages7/ping.go index 3d20aff..c6670d2 100644 --- a/messages7/ping.go +++ b/messages7/ping.go @@ -10,27 +10,28 @@ type Ping struct { ChunkHeader *chunk7.ChunkHeader } -func (msg Ping) MsgId() int { +func (msg *Ping) MsgId() int { return network7.MsgSysPing } -func (msg Ping) MsgType() network7.MsgType { +func (msg *Ping) MsgType() network7.MsgType { return network7.TypeNet } -func (msg Ping) System() bool { +func (msg *Ping) System() bool { return true } -func (msg Ping) Vital() bool { +func (msg *Ping) Vital() bool { return true } -func (msg Ping) Pack() []byte { +func (msg *Ping) Pack() []byte { return []byte{} } -func (msg *Ping) Unpack(u *packer.Unpacker) { +func (msg *Ping) Unpack(u *packer.Unpacker) error { + return nil } func (msg *Ping) Header() *chunk7.ChunkHeader { diff --git a/messages7/ping_reply.go b/messages7/ping_reply.go index e20e7b7..9ecf321 100644 --- a/messages7/ping_reply.go +++ b/messages7/ping_reply.go @@ -10,27 +10,28 @@ type PingReply struct { ChunkHeader *chunk7.ChunkHeader } -func (msg PingReply) MsgId() int { +func (msg *PingReply) MsgId() int { return network7.MsgSysPingReply } -func (msg PingReply) MsgType() network7.MsgType { +func (msg *PingReply) MsgType() network7.MsgType { return network7.TypeNet } -func (msg PingReply) System() bool { +func (msg *PingReply) System() bool { return true } -func (msg PingReply) Vital() bool { +func (msg *PingReply) Vital() bool { return true } -func (msg PingReply) Pack() []byte { +func (msg *PingReply) Pack() []byte { return []byte{} } -func (msg *PingReply) Unpack(u *packer.Unpacker) { +func (msg *PingReply) Unpack(u *packer.Unpacker) error { + return nil } func (msg *PingReply) Header() *chunk7.ChunkHeader { diff --git a/messages7/rcon_auth.go b/messages7/rcon_auth.go index b3981b8..c95cc93 100644 --- a/messages7/rcon_auth.go +++ b/messages7/rcon_auth.go @@ -14,30 +14,31 @@ type RconAuth struct { Password string } -func (msg RconAuth) MsgId() int { +func (msg *RconAuth) MsgId() int { return network7.MsgSysRconAuth } -func (msg RconAuth) MsgType() network7.MsgType { +func (msg *RconAuth) MsgType() network7.MsgType { return network7.TypeNet } -func (msg RconAuth) System() bool { +func (msg *RconAuth) System() bool { return true } -func (msg RconAuth) Vital() bool { +func (msg *RconAuth) Vital() bool { return true } -func (msg RconAuth) Pack() []byte { +func (msg *RconAuth) Pack() []byte { return slices.Concat( packer.PackStr(msg.Password), ) } -func (msg *RconAuth) Unpack(u *packer.Unpacker) { +func (msg *RconAuth) Unpack(u *packer.Unpacker) error { msg.Password = u.GetString() + return nil } func (msg *RconAuth) Header() *chunk7.ChunkHeader { diff --git a/messages7/rcon_auth_off.go b/messages7/rcon_auth_off.go index f577b49..279608a 100644 --- a/messages7/rcon_auth_off.go +++ b/messages7/rcon_auth_off.go @@ -10,27 +10,28 @@ type RconAuthOff struct { ChunkHeader *chunk7.ChunkHeader } -func (msg RconAuthOff) MsgId() int { +func (msg *RconAuthOff) MsgId() int { return network7.MsgSysRconAuthOff } -func (msg RconAuthOff) MsgType() network7.MsgType { +func (msg *RconAuthOff) MsgType() network7.MsgType { return network7.TypeNet } -func (msg RconAuthOff) System() bool { +func (msg *RconAuthOff) System() bool { return true } -func (msg RconAuthOff) Vital() bool { +func (msg *RconAuthOff) Vital() bool { return true } -func (msg RconAuthOff) Pack() []byte { +func (msg *RconAuthOff) Pack() []byte { return []byte{} } -func (msg *RconAuthOff) Unpack(u *packer.Unpacker) { +func (msg *RconAuthOff) Unpack(u *packer.Unpacker) error { + return nil } func (msg *RconAuthOff) Header() *chunk7.ChunkHeader { diff --git a/messages7/rcon_auth_on.go b/messages7/rcon_auth_on.go index b035d06..d051fc0 100644 --- a/messages7/rcon_auth_on.go +++ b/messages7/rcon_auth_on.go @@ -10,27 +10,28 @@ type RconAuthOn struct { ChunkHeader *chunk7.ChunkHeader } -func (msg RconAuthOn) MsgId() int { +func (msg *RconAuthOn) MsgId() int { return network7.MsgSysRconAuthOn } -func (msg RconAuthOn) MsgType() network7.MsgType { +func (msg *RconAuthOn) MsgType() network7.MsgType { return network7.TypeNet } -func (msg RconAuthOn) System() bool { +func (msg *RconAuthOn) System() bool { return true } -func (msg RconAuthOn) Vital() bool { +func (msg *RconAuthOn) Vital() bool { return true } -func (msg RconAuthOn) Pack() []byte { +func (msg *RconAuthOn) Pack() []byte { return []byte{} } -func (msg *RconAuthOn) Unpack(u *packer.Unpacker) { +func (msg *RconAuthOn) Unpack(u *packer.Unpacker) error { + return nil } func (msg *RconAuthOn) Header() *chunk7.ChunkHeader { diff --git a/messages7/rcon_cmd.go b/messages7/rcon_cmd.go index 0f2be90..c142e90 100644 --- a/messages7/rcon_cmd.go +++ b/messages7/rcon_cmd.go @@ -14,30 +14,31 @@ type RconCmd struct { Command string } -func (msg RconCmd) MsgId() int { +func (msg *RconCmd) MsgId() int { return network7.MsgSysRconCmd } -func (msg RconCmd) MsgType() network7.MsgType { +func (msg *RconCmd) MsgType() network7.MsgType { return network7.TypeNet } -func (msg RconCmd) System() bool { +func (msg *RconCmd) System() bool { return true } -func (msg RconCmd) Vital() bool { +func (msg *RconCmd) Vital() bool { return true } -func (msg RconCmd) Pack() []byte { +func (msg *RconCmd) Pack() []byte { return slices.Concat( packer.PackStr(msg.Command), ) } -func (msg *RconCmd) Unpack(u *packer.Unpacker) { +func (msg *RconCmd) Unpack(u *packer.Unpacker) error { msg.Command = u.GetString() + return nil } func (msg *RconCmd) Header() *chunk7.ChunkHeader { diff --git a/messages7/rcon_cmd_add.go b/messages7/rcon_cmd_add.go index b864378..1c45012 100644 --- a/messages7/rcon_cmd_add.go +++ b/messages7/rcon_cmd_add.go @@ -16,23 +16,23 @@ type RconCmdAdd struct { Params string } -func (msg RconCmdAdd) MsgId() int { +func (msg *RconCmdAdd) MsgId() int { return network7.MsgSysRconCmdAdd } -func (msg RconCmdAdd) MsgType() network7.MsgType { +func (msg *RconCmdAdd) MsgType() network7.MsgType { return network7.TypeNet } -func (msg RconCmdAdd) System() bool { +func (msg *RconCmdAdd) System() bool { return true } -func (msg RconCmdAdd) Vital() bool { +func (msg *RconCmdAdd) Vital() bool { return true } -func (msg RconCmdAdd) Pack() []byte { +func (msg *RconCmdAdd) Pack() []byte { return slices.Concat( packer.PackStr(msg.Name), packer.PackStr(msg.Help), @@ -40,10 +40,11 @@ func (msg RconCmdAdd) Pack() []byte { ) } -func (msg *RconCmdAdd) Unpack(u *packer.Unpacker) { +func (msg *RconCmdAdd) Unpack(u *packer.Unpacker) error { msg.Name = u.GetString() msg.Help = u.GetString() msg.Params = u.GetString() + return nil } func (msg *RconCmdAdd) Header() *chunk7.ChunkHeader { diff --git a/messages7/rcon_cmd_rem.go b/messages7/rcon_cmd_rem.go index c473ceb..99f657c 100644 --- a/messages7/rcon_cmd_rem.go +++ b/messages7/rcon_cmd_rem.go @@ -14,30 +14,31 @@ type RconCmdRem struct { Name string } -func (msg RconCmdRem) MsgId() int { +func (msg *RconCmdRem) MsgId() int { return network7.MsgSysRconCmdRem } -func (msg RconCmdRem) MsgType() network7.MsgType { +func (msg *RconCmdRem) MsgType() network7.MsgType { return network7.TypeNet } -func (msg RconCmdRem) System() bool { +func (msg *RconCmdRem) System() bool { return true } -func (msg RconCmdRem) Vital() bool { +func (msg *RconCmdRem) Vital() bool { return true } -func (msg RconCmdRem) Pack() []byte { +func (msg *RconCmdRem) Pack() []byte { return slices.Concat( packer.PackStr(msg.Name), ) } -func (msg *RconCmdRem) Unpack(u *packer.Unpacker) { +func (msg *RconCmdRem) Unpack(u *packer.Unpacker) error { msg.Name = u.GetString() + return nil } func (msg *RconCmdRem) Header() *chunk7.ChunkHeader { diff --git a/messages7/rcon_line.go b/messages7/rcon_line.go index 18580bd..60d1954 100644 --- a/messages7/rcon_line.go +++ b/messages7/rcon_line.go @@ -14,30 +14,31 @@ type RconLine struct { Line string } -func (msg RconLine) MsgId() int { +func (msg *RconLine) MsgId() int { return network7.MsgSysRconLine } -func (msg RconLine) MsgType() network7.MsgType { +func (msg *RconLine) MsgType() network7.MsgType { return network7.TypeNet } -func (msg RconLine) System() bool { +func (msg *RconLine) System() bool { return true } -func (msg RconLine) Vital() bool { +func (msg *RconLine) Vital() bool { return true } -func (msg RconLine) Pack() []byte { +func (msg *RconLine) Pack() []byte { return slices.Concat( packer.PackStr(msg.Line), ) } -func (msg *RconLine) Unpack(u *packer.Unpacker) { +func (msg *RconLine) Unpack(u *packer.Unpacker) error { msg.Line = u.GetString() + return nil } func (msg *RconLine) Header() *chunk7.ChunkHeader { diff --git a/messages7/ready.go b/messages7/ready.go index 4ceae22..1ba65eb 100644 --- a/messages7/ready.go +++ b/messages7/ready.go @@ -10,27 +10,28 @@ type Ready struct { ChunkHeader *chunk7.ChunkHeader } -func (msg Ready) MsgId() int { +func (msg *Ready) MsgId() int { return network7.MsgSysReady } -func (msg Ready) MsgType() network7.MsgType { +func (msg *Ready) MsgType() network7.MsgType { return network7.TypeNet } -func (msg Ready) System() bool { +func (msg *Ready) System() bool { return true } -func (msg Ready) Vital() bool { +func (msg *Ready) Vital() bool { return true } -func (msg Ready) Pack() []byte { +func (msg *Ready) Pack() []byte { return []byte{} } -func (msg *Ready) Unpack(u *packer.Unpacker) { +func (msg *Ready) Unpack(u *packer.Unpacker) error { + return nil } func (msg *Ready) Header() *chunk7.ChunkHeader { diff --git a/messages7/ready_to_enter.go b/messages7/ready_to_enter.go index 05066f9..db48dc7 100644 --- a/messages7/ready_to_enter.go +++ b/messages7/ready_to_enter.go @@ -10,27 +10,28 @@ type ReadyToEnter struct { ChunkHeader *chunk7.ChunkHeader } -func (msg ReadyToEnter) MsgId() int { +func (msg *ReadyToEnter) MsgId() int { return network7.MsgGameReadyToEnter } -func (msg ReadyToEnter) MsgType() network7.MsgType { +func (msg *ReadyToEnter) MsgType() network7.MsgType { return network7.TypeNet } -func (msg ReadyToEnter) System() bool { +func (msg *ReadyToEnter) System() bool { return false } -func (msg ReadyToEnter) Vital() bool { +func (msg *ReadyToEnter) Vital() bool { return true } -func (msg ReadyToEnter) Pack() []byte { +func (msg *ReadyToEnter) Pack() []byte { return []byte{} } -func (msg *ReadyToEnter) Unpack(u *packer.Unpacker) { +func (msg *ReadyToEnter) Unpack(u *packer.Unpacker) error { + return nil } func (msg *ReadyToEnter) Header() *chunk7.ChunkHeader { diff --git a/messages7/request_map_data.go b/messages7/request_map_data.go index 3273315..dcc2d22 100644 --- a/messages7/request_map_data.go +++ b/messages7/request_map_data.go @@ -10,27 +10,28 @@ type RequestMapData struct { ChunkHeader *chunk7.ChunkHeader } -func (msg RequestMapData) MsgId() int { +func (msg *RequestMapData) MsgId() int { return network7.MsgSysRequestMapData } -func (msg RequestMapData) MsgType() network7.MsgType { +func (msg *RequestMapData) MsgType() network7.MsgType { return network7.TypeNet } -func (msg RequestMapData) System() bool { +func (msg *RequestMapData) System() bool { return true } -func (msg RequestMapData) Vital() bool { +func (msg *RequestMapData) Vital() bool { return true } -func (msg RequestMapData) Pack() []byte { +func (msg *RequestMapData) Pack() []byte { return []byte{} } -func (msg *RequestMapData) Unpack(u *packer.Unpacker) { +func (msg *RequestMapData) Unpack(u *packer.Unpacker) error { + return nil } func (msg *RequestMapData) Header() *chunk7.ChunkHeader { diff --git a/messages7/server_info.go b/messages7/server_info.go index 28077b1..58b747c 100644 --- a/messages7/server_info.go +++ b/messages7/server_info.go @@ -24,23 +24,23 @@ type ServerInfo struct { MaxClients int } -func (msg ServerInfo) MsgId() int { +func (msg *ServerInfo) MsgId() int { return network7.MsgSysServerInfo } -func (msg ServerInfo) MsgType() network7.MsgType { +func (msg *ServerInfo) MsgType() network7.MsgType { return network7.TypeNet } -func (msg ServerInfo) System() bool { +func (msg *ServerInfo) System() bool { return true } -func (msg ServerInfo) Vital() bool { +func (msg *ServerInfo) Vital() bool { return true } -func (msg ServerInfo) Pack() []byte { +func (msg *ServerInfo) Pack() []byte { return slices.Concat( packer.PackStr(msg.Version), packer.PackStr(msg.Name), @@ -56,7 +56,7 @@ func (msg ServerInfo) Pack() []byte { ) } -func (msg *ServerInfo) Unpack(u *packer.Unpacker) { +func (msg *ServerInfo) Unpack(u *packer.Unpacker) error { msg.Version = u.GetString() msg.Name = u.GetString() msg.Hostname = u.GetString() @@ -68,6 +68,7 @@ func (msg *ServerInfo) Unpack(u *packer.Unpacker) { msg.PlayerSlots = u.GetInt() msg.ClientCount = u.GetInt() msg.MaxClients = u.GetInt() + return nil } func (msg *ServerInfo) Header() *chunk7.ChunkHeader { diff --git a/messages7/snap.go b/messages7/snap.go index 2aff0f6..9ed9861 100644 --- a/messages7/snap.go +++ b/messages7/snap.go @@ -20,23 +20,23 @@ type Snap struct { Data []byte } -func (msg Snap) MsgId() int { +func (msg *Snap) MsgId() int { return network7.MsgSysSnap } -func (msg Snap) MsgType() network7.MsgType { +func (msg *Snap) MsgType() network7.MsgType { return network7.TypeNet } -func (msg Snap) System() bool { +func (msg *Snap) System() bool { return true } -func (msg Snap) Vital() bool { +func (msg *Snap) Vital() bool { return false } -func (msg Snap) Pack() []byte { +func (msg *Snap) Pack() []byte { return slices.Concat( packer.PackInt(msg.GameTick), packer.PackInt(msg.DeltaTick), @@ -44,11 +44,11 @@ func (msg Snap) Pack() []byte { packer.PackInt(msg.Part), packer.PackInt(msg.Crc), packer.PackInt(msg.PartSize), - msg.Data[:], + msg.Data, ) } -func (msg *Snap) Unpack(u *packer.Unpacker) { +func (msg *Snap) Unpack(u *packer.Unpacker) error { msg.GameTick = u.GetInt() msg.DeltaTick = u.GetInt() msg.NumParts = u.GetInt() @@ -56,6 +56,7 @@ func (msg *Snap) Unpack(u *packer.Unpacker) { msg.Crc = u.GetInt() msg.PartSize = u.GetInt() msg.Data = u.Rest() + return nil } func (msg *Snap) Header() *chunk7.ChunkHeader { diff --git a/messages7/snap_empty.go b/messages7/snap_empty.go index f549dbc..b6ad052 100644 --- a/messages7/snap_empty.go +++ b/messages7/snap_empty.go @@ -15,32 +15,33 @@ type SnapEmpty struct { DeltaTick int } -func (msg SnapEmpty) MsgId() int { +func (msg *SnapEmpty) MsgId() int { return network7.MsgSysSnapEmpty } -func (msg SnapEmpty) MsgType() network7.MsgType { +func (msg *SnapEmpty) MsgType() network7.MsgType { return network7.TypeNet } -func (msg SnapEmpty) System() bool { +func (msg *SnapEmpty) System() bool { return true } -func (msg SnapEmpty) Vital() bool { +func (msg *SnapEmpty) Vital() bool { return false } -func (msg SnapEmpty) Pack() []byte { +func (msg *SnapEmpty) Pack() []byte { return slices.Concat( packer.PackInt(msg.GameTick), packer.PackInt(msg.DeltaTick), ) } -func (msg *SnapEmpty) Unpack(u *packer.Unpacker) { +func (msg *SnapEmpty) Unpack(u *packer.Unpacker) error { msg.GameTick = u.GetInt() msg.DeltaTick = u.GetInt() + return nil } func (msg *SnapEmpty) Header() *chunk7.ChunkHeader { diff --git a/messages7/snap_single.go b/messages7/snap_single.go index 4facb36..71ba708 100644 --- a/messages7/snap_single.go +++ b/messages7/snap_single.go @@ -18,38 +18,39 @@ type SnapSingle struct { Data []byte } -func (msg SnapSingle) MsgId() int { +func (msg *SnapSingle) MsgId() int { return network7.MsgSysSnapSingle } -func (msg SnapSingle) MsgType() network7.MsgType { +func (msg *SnapSingle) MsgType() network7.MsgType { return network7.TypeNet } -func (msg SnapSingle) System() bool { +func (msg *SnapSingle) System() bool { return true } -func (msg SnapSingle) Vital() bool { +func (msg *SnapSingle) Vital() bool { return false } -func (msg SnapSingle) Pack() []byte { +func (msg *SnapSingle) Pack() []byte { return slices.Concat( packer.PackInt(msg.GameTick), packer.PackInt(msg.DeltaTick), packer.PackInt(msg.Crc), packer.PackInt(msg.PartSize), - msg.Data[:], + msg.Data, ) } -func (msg *SnapSingle) Unpack(u *packer.Unpacker) { +func (msg *SnapSingle) Unpack(u *packer.Unpacker) error { msg.GameTick = u.GetInt() msg.DeltaTick = u.GetInt() msg.Crc = u.GetInt() msg.PartSize = u.GetInt() msg.Data = u.Rest() + return nil } func (msg *SnapSingle) Header() *chunk7.ChunkHeader { diff --git a/messages7/snap_small.go b/messages7/snap_small.go index 67b5b56..70d1db7 100644 --- a/messages7/snap_small.go +++ b/messages7/snap_small.go @@ -11,27 +11,28 @@ type SnapSmall struct { ChunkHeader *chunk7.ChunkHeader } -func (msg SnapSmall) MsgId() int { +func (msg *SnapSmall) MsgId() int { return network7.MsgSysSnapSmall } -func (msg SnapSmall) MsgType() network7.MsgType { +func (msg *SnapSmall) MsgType() network7.MsgType { return network7.TypeNet } -func (msg SnapSmall) System() bool { +func (msg *SnapSmall) System() bool { return true } -func (msg SnapSmall) Vital() bool { +func (msg *SnapSmall) Vital() bool { return false } -func (msg SnapSmall) Pack() []byte { +func (msg *SnapSmall) Pack() []byte { return []byte{} } -func (msg *SnapSmall) Unpack(u *packer.Unpacker) { +func (msg *SnapSmall) Unpack(u *packer.Unpacker) error { + return nil } func (msg *SnapSmall) Header() *chunk7.ChunkHeader { diff --git a/messages7/sv_broadcast.go b/messages7/sv_broadcast.go index b8e828d..2912cff 100644 --- a/messages7/sv_broadcast.go +++ b/messages7/sv_broadcast.go @@ -12,28 +12,29 @@ type SvBroadcast struct { Message string } -func (msg SvBroadcast) MsgId() int { +func (msg *SvBroadcast) MsgId() int { return network7.MsgGameSvBroadcast } -func (msg SvBroadcast) MsgType() network7.MsgType { +func (msg *SvBroadcast) MsgType() network7.MsgType { return network7.TypeNet } -func (msg SvBroadcast) System() bool { +func (msg *SvBroadcast) System() bool { return false } -func (msg SvBroadcast) Vital() bool { +func (msg *SvBroadcast) Vital() bool { return true } -func (msg SvBroadcast) Pack() []byte { +func (msg *SvBroadcast) Pack() []byte { return packer.PackStr(msg.Message) } -func (msg *SvBroadcast) Unpack(u *packer.Unpacker) { +func (msg *SvBroadcast) Unpack(u *packer.Unpacker) error { msg.Message = u.GetString() + return nil } func (msg *SvBroadcast) Header() *chunk7.ChunkHeader { diff --git a/messages7/sv_chat.go b/messages7/sv_chat.go index 50430dc..4fc4831 100644 --- a/messages7/sv_chat.go +++ b/messages7/sv_chat.go @@ -17,23 +17,23 @@ type SvChat struct { Message string } -func (msg SvChat) MsgId() int { +func (msg *SvChat) MsgId() int { return network7.MsgGameSvChat } -func (msg SvChat) MsgType() network7.MsgType { +func (msg *SvChat) MsgType() network7.MsgType { return network7.TypeNet } -func (msg SvChat) System() bool { +func (msg *SvChat) System() bool { return false } -func (msg SvChat) Vital() bool { +func (msg *SvChat) Vital() bool { return true } -func (msg SvChat) Pack() []byte { +func (msg *SvChat) Pack() []byte { return slices.Concat( packer.PackInt(int(msg.Mode)), packer.PackInt(msg.ClientId), @@ -42,11 +42,13 @@ func (msg SvChat) Pack() []byte { ) } -func (msg *SvChat) Unpack(u *packer.Unpacker) { +func (msg *SvChat) Unpack(u *packer.Unpacker) error { msg.Mode = network7.ChatMode(u.GetInt()) msg.ClientId = u.GetInt() msg.TargetId = u.GetInt() msg.Message = u.GetString() + + return nil } func (msg *SvChat) Header() *chunk7.ChunkHeader { diff --git a/messages7/sv_client_info.go b/messages7/sv_client_info.go index 0014af9..dc609ca 100644 --- a/messages7/sv_client_info.go +++ b/messages7/sv_client_info.go @@ -53,7 +53,7 @@ func (info *SvClientInfo) Vital() bool { return true } -func (msg SvClientInfo) Pack() []byte { +func (msg *SvClientInfo) Pack() []byte { return slices.Concat( packer.PackInt(msg.ClientId), packer.PackBool(msg.Local), @@ -82,7 +82,7 @@ func (msg SvClientInfo) Pack() []byte { ) } -func (info *SvClientInfo) Unpack(u *packer.Unpacker) { +func (info *SvClientInfo) Unpack(u *packer.Unpacker) error { info.ClientId = u.GetInt() info.Local = u.GetInt() != 0 info.Team = u.GetInt() @@ -107,6 +107,8 @@ func (info *SvClientInfo) Unpack(u *packer.Unpacker) { info.ColorFeet = u.GetInt() info.ColorEyes = u.GetInt() info.Silent = u.GetInt() != 0 + + return nil } func (msg *SvClientInfo) Header() *chunk7.ChunkHeader { diff --git a/messages7/sv_client_info_test.go b/messages7/sv_client_info_test.go index 44727d8..dfb6c10 100644 --- a/messages7/sv_client_info_test.go +++ b/messages7/sv_client_info_test.go @@ -1,9 +1,9 @@ package messages7 import ( - "reflect" "testing" + "github.com/teeworlds-go/go-teeworlds-protocol/internal/testutils/require" "github.com/teeworlds-go/go-teeworlds-protocol/packer" ) @@ -21,26 +21,21 @@ func TestUnpackClientInfo(t *testing.T) { }) info := SvClientInfo{} - info.Unpack(&u) + err := info.Unpack(&u) + require.NoError(t, err) { - got := info.Eyes want := "standard" - if got != want { - t.Errorf("got %v, wanted %v", got, want) - } + got := info.Eyes + require.Equal(t, want, got) - got = info.Decoration want = "" - if got != want { - t.Errorf("got %v, wanted %v", got, want) - } + got = info.Decoration + require.Equal(t, want, got) - got = info.Marking want = "duodonny" - if got != want { - t.Errorf("got %v, wanted %v", got, want) - } + got = info.Marking + require.Equal(t, want, got) } wantedInfo := SvClientInfo{ @@ -69,8 +64,5 @@ func TestUnpackClientInfo(t *testing.T) { ColorEyes: 65408, Silent: true, } - - if !reflect.DeepEqual(info, wantedInfo) { - t.Errorf("got %v, wanted %v", info, wantedInfo) - } + require.Equal(t, wantedInfo, info) } diff --git a/messages7/sv_motd.go b/messages7/sv_motd.go index 3150324..44fafdb 100644 --- a/messages7/sv_motd.go +++ b/messages7/sv_motd.go @@ -12,28 +12,29 @@ type SvMotd struct { Message string } -func (msg SvMotd) MsgId() int { +func (msg *SvMotd) MsgId() int { return network7.MsgGameSvMotd } -func (msg SvMotd) MsgType() network7.MsgType { +func (msg *SvMotd) MsgType() network7.MsgType { return network7.TypeNet } -func (msg SvMotd) System() bool { +func (msg *SvMotd) System() bool { return false } -func (msg SvMotd) Vital() bool { +func (msg *SvMotd) Vital() bool { return true } -func (msg SvMotd) Pack() []byte { +func (msg *SvMotd) Pack() []byte { return packer.PackStr(msg.Message) } -func (msg *SvMotd) Unpack(u *packer.Unpacker) { +func (msg *SvMotd) Unpack(u *packer.Unpacker) error { msg.Message = u.GetString() + return nil } func (msg *SvMotd) Header() *chunk7.ChunkHeader { diff --git a/messages7/sv_team.go b/messages7/sv_team.go index 1e1fbc0..b9eab55 100644 --- a/messages7/sv_team.go +++ b/messages7/sv_team.go @@ -16,23 +16,23 @@ type SvTeam struct { CooldownTick int } -func (msg SvTeam) MsgId() int { +func (msg *SvTeam) MsgId() int { return network7.MsgGameSvTeam } -func (msg SvTeam) MsgType() network7.MsgType { +func (msg *SvTeam) MsgType() network7.MsgType { return network7.TypeNet } -func (msg SvTeam) System() bool { +func (msg *SvTeam) System() bool { return false } -func (msg SvTeam) Vital() bool { +func (msg *SvTeam) Vital() bool { return true } -func (msg SvTeam) Pack() []byte { +func (msg *SvTeam) Pack() []byte { return slices.Concat( packer.PackInt(msg.ClientId), packer.PackBool(msg.Silent), @@ -40,10 +40,11 @@ func (msg SvTeam) Pack() []byte { ) } -func (msg *SvTeam) Unpack(u *packer.Unpacker) { +func (msg *SvTeam) Unpack(u *packer.Unpacker) error { msg.ClientId = u.GetInt() msg.Silent = u.GetInt() != 0 msg.CooldownTick = u.GetInt() + return nil } func (msg *SvTeam) Header() *chunk7.ChunkHeader { diff --git a/messages7/unknown.go b/messages7/unknown.go index 568abb1..fc4d903 100644 --- a/messages7/unknown.go +++ b/messages7/unknown.go @@ -14,40 +14,42 @@ type Unknown struct { // can either be a control message or a game/system message Data []byte Type network7.MsgType + + msgId int // TODO: is that supposed to be exported? } -func (msg Unknown) MsgId() int { - msgId := packer.UnpackInt(msg.Data) +func (msg *Unknown) MsgId() int { if msg.Type == network7.TypeControl { - return msgId + return msg.msgId } - msgId >>= 1 - return msgId + return msg.msgId >> 1 } -func (msg Unknown) MsgType() network7.MsgType { +func (msg *Unknown) MsgType() network7.MsgType { return msg.Type } -func (msg Unknown) System() bool { - msgId := packer.UnpackInt(msg.Data) +func (msg *Unknown) System() bool { if msg.Type == network7.TypeControl { return false } - sys := msgId&1 != 0 + sys := msg.msgId&1 != 0 return sys } -func (msg Unknown) Vital() bool { +func (msg *Unknown) Vital() bool { panic("You are not mean't to pack unknown messages. Use msg.Header().Vital instead.") } -func (msg Unknown) Pack() []byte { +func (msg *Unknown) Pack() []byte { return msg.Data } -func (msg *Unknown) Unpack(u *packer.Unpacker) { +func (msg *Unknown) Unpack(u *packer.Unpacker) error { msg.Data = u.Rest() + msgId := packer.UnpackInt(msg.Data) + msg.msgId = msgId + return nil } func (msg *Unknown) Header() *chunk7.ChunkHeader { diff --git a/network7/network7.go b/network7/network7.go index e2ca2ad..ad45bcc 100644 --- a/network7/network7.go +++ b/network7/network7.go @@ -19,6 +19,9 @@ const ( MsgCtrlToken = 0x05 MsgCtrlClose = 0x04 + // TODO: these should preferrably all be devide dinto different type dintegers + // same as ChatMode, etc. so that the user can easily see which integer to pass + // to which function as which parameter MsgSysInfo = 1 MsgSysMapChange = 2 MsgSysMapData = 3 diff --git a/packer/packer_state_test.go b/packer/packer_state_test.go index 5fc8298..a541712 100644 --- a/packer/packer_state_test.go +++ b/packer/packer_state_test.go @@ -1,8 +1,9 @@ package packer import ( - "reflect" "testing" + + "github.com/teeworlds-go/go-teeworlds-protocol/internal/testutils/require" ) // rest @@ -12,21 +13,15 @@ func TestUnpackRest(t *testing.T) { u.Reset([]byte{0x01, 0xff, 0xaa}) { - got := u.GetInt() want := 1 - - if got != want { - t.Errorf("got %v, wanted %v", got, want) - } + got := u.GetInt() + require.Equal(t, want, got) } { - got := u.Rest() want := []byte{0xff, 0xaa} - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + got := u.Rest() + require.Equal(t, want, got) } } @@ -47,20 +42,14 @@ func TestUnpackClientInfo(t *testing.T) { { // message id - got := u.GetInt() want := 36 - - if got != want { - t.Errorf("got %v, wanted %v", got, want) - } + got := u.GetInt() + require.Equal(t, want, got) // client id - got = u.GetInt() want = 0 - - if got != want { - t.Errorf("got %v, wanted %v", got, want) - } + got = u.GetInt() + require.Equal(t, want, got) u.GetInt() // Local bool u.GetInt() // Team int @@ -68,40 +57,28 @@ func TestUnpackClientInfo(t *testing.T) { { // name - got := u.GetString() want := "gopher" - - if got != want { - t.Errorf("got %v, wanted %v", got, want) - } + got := u.GetString() + require.Equal(t, want, got) // clan - got = u.GetString() want = "" - - if got != want { - t.Errorf("got %v, wanted %v", got, want) - } + got = u.GetString() + require.Equal(t, want, got) } { // country - got := u.GetInt() want := -1 - - if got != want { - t.Errorf("got %v, wanted %v", got, want) - } + got := u.GetInt() + require.Equal(t, want, got) } { // body - got := u.GetString() want := "greensward" - - if got != want { - t.Errorf("got %v, wanted %v", got, want) - } + got := u.GetString() + require.Equal(t, want, got) } } @@ -111,64 +88,44 @@ func TestUnpackSimpleInts(t *testing.T) { u := Unpacker{} u.Reset([]byte{0x01, 0x02, 0x03, 0x0f}) - got := u.GetInt() want := 1 + got := u.GetInt() + require.Equal(t, want, got) - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } - - got = u.GetInt() want = 2 - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } - got = u.GetInt() + require.Equal(t, want, got) + want = 3 - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } - got = u.GetInt() - want = 15 + require.Equal(t, want, got) - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + want = 15 + got = u.GetInt() + require.Equal(t, want, got) } func TestUnpackString(t *testing.T) { u := Unpacker{} u.Reset([]byte{'f', 'o', 'o', 0x00}) - got := u.GetString() want := "foo" - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + got := u.GetString() + require.Equal(t, want, got) } func TestUnpackTwoStrings(t *testing.T) { u := Unpacker{} u.Reset([]byte{'f', 'o', 'o', 0x00, 'b', 'a', 'r', 0x00}) - got := u.GetString() want := "foo" + got := u.GetString() + require.Equal(t, want, got) - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } - - got = u.GetString() want = "bar" + got = u.GetString() + require.Equal(t, want, got) - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } } func TestUnpackMixed(t *testing.T) { @@ -177,45 +134,30 @@ func TestUnpackMixed(t *testing.T) { // ints { - got := u.GetInt() want := 15 + got := u.GetInt() + require.Equal(t, want, got) - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } - - got = u.GetInt() want = 15 - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + got = u.GetInt() + require.Equal(t, want, got) } // strings { - got := u.GetString() want := "foo" + got := u.GetString() + require.Equal(t, want, got) - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } - - got = u.GetString() want = "bar" - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + got = u.GetString() + require.Equal(t, want, got) } // ints { - got := u.GetInt() want := 1 - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + got := u.GetInt() + require.Equal(t, want, got) } } diff --git a/packer/packer_test.go b/packer/packer_test.go index 32656ca..b04ef3d 100644 --- a/packer/packer_test.go +++ b/packer/packer_test.go @@ -1,145 +1,95 @@ package packer import ( - "reflect" "testing" + + "github.com/teeworlds-go/go-teeworlds-protocol/internal/testutils/require" ) // pack func TestPackEmptyString(t *testing.T) { - got := PackStr("") want := []byte{0x00} - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + got := PackStr("") + require.Equal(t, want, got) } func TestPackSimpleString(t *testing.T) { - got := PackStr("foo") want := []byte{'f', 'o', 'o', 0x00} - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + got := PackStr("foo") + require.Equal(t, want, got) } func TestPackSmallPositiveInts(t *testing.T) { - got := PackInt(1) want := []byte{0x01} - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + got := PackInt(1) + require.Equal(t, want, got) } func TestPackMultiBytePositiveInts(t *testing.T) { - got := PackInt(63) want := []byte{0x3F} + got := PackInt(63) + require.Equal(t, want, got) - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } - - got = PackInt(64) want = []byte{0x80, 0x01} + got = PackInt(64) + require.Equal(t, want, got) - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } - - got = PackInt(65) want = []byte{0x81, 0x01} - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + got = PackInt(65) + require.Equal(t, want, got) } func TestPackSmallNegativeInts(t *testing.T) { - got := PackInt(-1) want := []byte{0x40} + got := PackInt(-1) + require.Equal(t, want, got) - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } - - got = PackInt(-2) want = []byte{0x41} - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + got = PackInt(-2) + require.Equal(t, want, got) } func TestPackMultiByteNegativeInts(t *testing.T) { - got := PackInt(-63) want := []byte{0x7E} - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + got := PackInt(-63) + require.Equal(t, want, got) got = PackInt(-64) want = []byte{0x7F} + require.Equal(t, want, got) - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } - - got = PackInt(-65) want = []byte{0xC0, 0x01} - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + got = PackInt(-65) + require.Equal(t, want, got) } // unpack func TestUnpackSmallPositiveInts(t *testing.T) { - got := UnpackInt([]byte{0x01}) want := 1 + got := UnpackInt([]byte{0x01}) + require.Equal(t, want, got) - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } - - got = UnpackInt([]byte{0x02}) want = 2 + got = UnpackInt([]byte{0x02}) + require.Equal(t, want, got) - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } - - got = UnpackInt([]byte{0x03}) want = 3 - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + got = UnpackInt([]byte{0x03}) + require.Equal(t, want, got) } func TestUnpackMultiBytePositiveInts(t *testing.T) { - got := UnpackInt([]byte{0x3f}) want := 63 + got := UnpackInt([]byte{0x3f}) + require.Equal(t, want, got) - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } - - got = UnpackInt([]byte{0x80, 0x01}) want = 64 + got = UnpackInt([]byte{0x80, 0x01}) + require.Equal(t, want, got) - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } - - got = UnpackInt([]byte{0x81, 0x01}) want = 65 - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + got = UnpackInt([]byte{0x81, 0x01}) + require.Equal(t, want, got) } diff --git a/protocol7/packet.go b/protocol7/packet.go index 749de77..b368c94 100644 --- a/protocol7/packet.go +++ b/protocol7/packet.go @@ -1,6 +1,7 @@ package protocol7 import ( + "fmt" "slices" "github.com/teeworlds-go/go-teeworlds-protocol/chunk7" @@ -11,6 +12,7 @@ import ( ) const ( + // TODO: these should preferrably be typed integers packetFlagControl = 1 packetFlagResend = 2 packetFlagCompression = 4 @@ -80,158 +82,122 @@ func PackChunk(msg messages7.NetMessage, connection *Session) []byte { return data } -func (packet *Packet) unpackSystem(msgId int, chunk chunk7.Chunk, u *packer.Unpacker) bool { - if msgId == network7.MsgSysInfo { - msg := &messages7.Info{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysMapChange { - msg := &messages7.MapChange{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysMapData { - msg := &messages7.MapData{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysServerInfo { - msg := &messages7.ServerInfo{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysConReady { - msg := &messages7.ConReady{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysSnap { - msg := &messages7.Snap{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysSnapEmpty { - msg := &messages7.SnapEmpty{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysSnapSingle { - msg := &messages7.SnapSingle{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysSnapSmall { - msg := &messages7.SnapSmall{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysInputTiming { - msg := &messages7.InputTiming{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysRconAuthOn { - msg := &messages7.RconAuthOn{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysRconAuthOff { - msg := &messages7.RconAuthOff{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysRconLine { - msg := &messages7.RconLine{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysRconCmdAdd { - msg := &messages7.RconCmdAdd{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysRconCmdRem { - msg := &messages7.RconCmdRem{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysAuthChallenge { - msg := &messages7.AuthChallenge{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysAuthResult { - msg := &messages7.AuthResult{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysReady { - msg := &messages7.Ready{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysEnterGame { - msg := &messages7.EnterGame{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysInput { - msg := &messages7.Input{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysRconCmd { - msg := &messages7.RconCmd{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysRconAuth { - msg := &messages7.RconAuth{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysRequestMapData { - msg := &messages7.RequestMapData{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysAuthStart { - msg := &messages7.AuthStart{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysAuthResponse { - msg := &messages7.AuthResponse{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysPing { - msg := &messages7.Ping{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysPingReply { - msg := &messages7.PingReply{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysError { - msg := &messages7.Error{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysMaplistEntryAdd { - msg := &messages7.MaplistEntryAdd{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgSysMaplistEntryRem { - msg := &messages7.MaplistEntryRem{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else { - return false +func (packet *Packet) unpackSystem(msgId int, chunk chunk7.Chunk, u *packer.Unpacker) (bool, error) { + + var msg messages7.NetMessage + + switch msgId { + case network7.MsgSysInfo: + msg = &messages7.Info{} + case network7.MsgSysMapChange: + msg = &messages7.MapChange{} + case network7.MsgSysMapData: + msg = &messages7.MapData{} + case network7.MsgSysServerInfo: + msg = &messages7.ServerInfo{} + case network7.MsgSysConReady: + msg = &messages7.ConReady{} + case network7.MsgSysSnap: + msg = &messages7.Snap{} + case network7.MsgSysSnapEmpty: + msg = &messages7.SnapEmpty{} + case network7.MsgSysSnapSingle: + msg = &messages7.SnapSingle{} + case network7.MsgSysSnapSmall: + msg = &messages7.SnapSmall{} + case network7.MsgSysInputTiming: + msg = &messages7.InputTiming{} + case network7.MsgSysRconAuthOn: + msg = &messages7.RconAuthOn{} + case network7.MsgSysRconAuthOff: + msg = &messages7.RconAuthOff{} + case network7.MsgSysRconLine: + msg = &messages7.RconLine{} + case network7.MsgSysRconCmdAdd: + msg = &messages7.RconCmdAdd{} + case network7.MsgSysRconCmdRem: + msg = &messages7.RconCmdRem{} + case network7.MsgSysAuthChallenge: + msg = &messages7.AuthChallenge{} + case network7.MsgSysAuthResult: + msg = &messages7.AuthResult{} + case network7.MsgSysReady: + msg = &messages7.Ready{} + case network7.MsgSysEnterGame: + msg = &messages7.EnterGame{} + case network7.MsgSysInput: + msg = &messages7.Input{} + case network7.MsgSysRconCmd: + msg = &messages7.RconCmd{} + case network7.MsgSysRconAuth: + msg = &messages7.RconAuth{} + case network7.MsgSysRequestMapData: + msg = &messages7.RequestMapData{} + case network7.MsgSysAuthStart: + msg = &messages7.AuthStart{} + case network7.MsgSysAuthResponse: + msg = &messages7.AuthResponse{} + case network7.MsgSysPing: + msg = &messages7.Ping{} + case network7.MsgSysPingReply: + msg = &messages7.PingReply{} + case network7.MsgSysError: + msg = &messages7.Error{} + case network7.MsgSysMaplistEntryAdd: + msg = &messages7.MaplistEntryAdd{} + case network7.MsgSysMaplistEntryRem: + msg = &messages7.MaplistEntryRem{} + default: + return false, nil } - // packet.Messages[len(packet.Messages)-1].SetHeader(&chunk.Header) - return true + + header := chunk.Header // decouple memory by copying only the needed value + msg.SetHeader(&header) + + err := msg.Unpack(u) + if err != nil { + // in case of an error, the user is not supposed to continue + // working with the returned first value + return false, err + } + + packet.Messages = append(packet.Messages, msg) + return true, nil + } -func (packet *Packet) unpackGame(msgId int, chunk chunk7.Chunk, u *packer.Unpacker) bool { - if msgId == network7.MsgGameReadyToEnter { - msg := &messages7.ReadyToEnter{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgGameSvMotd { - msg := &messages7.SvMotd{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgGameSvChat { - msg := &messages7.SvChat{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else if msgId == network7.MsgGameSvClientInfo { - msg := &messages7.SvClientInfo{ChunkHeader: &chunk.Header} - msg.Unpack(u) - packet.Messages = append(packet.Messages, msg) - } else { - return false +func (packet *Packet) unpackGame(msgId int, chunk chunk7.Chunk, u *packer.Unpacker) (bool, error) { + + var msg messages7.NetMessage + + switch msgId { + case network7.MsgGameReadyToEnter: + msg = &messages7.ReadyToEnter{} + case network7.MsgGameSvMotd: + msg = &messages7.SvMotd{} + case network7.MsgGameSvChat: + msg = &messages7.SvChat{} + case network7.MsgGameSvClientInfo: + msg = &messages7.SvClientInfo{} + default: + return false, nil } - return true + + header := chunk.Header // decouple memory by copying only the needed value + msg.SetHeader(&header) + err := msg.Unpack(u) + if err != nil { + // in case of an error, the user is not supposed to continue + // working with the returned first value + return false, err + } + + packet.Messages = append(packet.Messages, msg) + return true, nil + } -func (packet *Packet) unpackChunk(chunk chunk7.Chunk) bool { +func (packet *Packet) unpackChunk(chunk chunk7.Chunk) (bool, error) { u := packer.Unpacker{} u.Reset(chunk.Data) @@ -249,12 +215,20 @@ func (packet *Packet) unpackChunk(chunk chunk7.Chunk) bool { func (packet *Packet) unpackPayload(payload []byte) { chunks := chunk7.UnpackChunks(payload) + var ( + // reuse variables to avoid reallocation + ok bool + err error + ) + for _, c := range chunks { - if packet.unpackChunk(c) == false { + ok, err = packet.unpackChunk(c) + if err != nil || !ok { + header := c.Header // decouple memory by copying only the needed value unknown := &messages7.Unknown{ - ChunkHeader: &c.Header, - Data: slices.Concat(c.Header.Pack(), c.Data), Type: network7.TypeNet, + ChunkHeader: &header, + Data: slices.Concat(c.Header.Pack(), c.Data), } packet.Messages = append(packet.Messages, unknown) } @@ -264,37 +238,42 @@ func (packet *Packet) unpackPayload(payload []byte) { // Only returns an error if there is invalid huffman compression applied // Unknown messages will be unpacked as messages7.Unknown // There is no validation no messages will be dropped -func (packet *Packet) Unpack(data []byte) error { - packet.Header.Unpack(data[:7]) - payload := data[7:] +func (packet *Packet) Unpack(data []byte) (err error) { + header, payload := data[:7], data[7:] + packet.Header.Unpack(header) if packet.Header.Flags.Control { unpacker := packer.Unpacker{} unpacker.Reset(payload) ctrlMsg := unpacker.GetInt() - if ctrlMsg == network7.MsgCtrlToken { - msg := &messages7.CtrlToken{} - msg.Unpack(&unpacker) - packet.Messages = append(packet.Messages, msg) - } else if ctrlMsg == network7.MsgCtrlAccept { - packet.Messages = append(packet.Messages, &messages7.CtrlAccept{}) - } else if ctrlMsg == network7.MsgCtrlClose { - msg := &messages7.CtrlClose{} - msg.Unpack(&unpacker) - packet.Messages = append(packet.Messages, msg) - } else { - unknown := &messages7.Unknown{ - Data: payload, + + var msg messages7.NetMessage + switch ctrlMsg { + case network7.MsgCtrlToken: + msg = &messages7.CtrlToken{} + case network7.MsgCtrlAccept: + msg = &messages7.CtrlAccept{} + case network7.MsgCtrlClose: + msg = &messages7.CtrlClose{} + default: + msg = &messages7.Unknown{ Type: network7.TypeControl, } - packet.Messages = append(packet.Messages, unknown) } + + err := msg.Unpack(&unpacker) + if err != nil { + return err + } + + packet.Messages = append(packet.Messages, msg) return nil } if packet.Header.Flags.Compression { + // TODO: try avoiding repeated initialization of the huffman tree structure + // move this into the Packet struct or even further up huff := huffman.Huffman{} - var err error payload, err = huff.Decompress(payload) if err != nil { return err @@ -319,10 +298,12 @@ func (packet *Packet) Pack(connection *Session) []byte { packet.Header.NumChunks = len(packet.Messages) if control { - packet.Header.Flags.Connless = false - packet.Header.Flags.Compression = false - packet.Header.Flags.Resend = false - packet.Header.Flags.Control = true + packet.Header.Flags = PacketFlags{ + Connless: false, + Compression: false, + Resend: false, + Control: true, + } } if packet.Header.Flags.Compression { @@ -375,23 +356,36 @@ func (header *PacketHeader) Pack() []byte { ) } -func (header *PacketHeader) Unpack(packet []byte) { - header.Flags.Unpack(packet) +func (header *PacketHeader) Unpack(packet []byte) (err error) { + if len(packet) < 7 { + return fmt.Errorf("failed to unpack packet header: packet too short: size %d", len(packet)) + } + + err = header.Flags.Unpack(packet) + if err != nil { + return fmt.Errorf("failed to unpack packet header: %w", err) + } header.Ack = (int(packet[0]&0x3) << 8) | int(packet[1]) header.NumChunks = int(packet[2]) copy(header.Token[:], packet[3:7]) + return nil } -func (flags *PacketFlags) Unpack(packetHeaderRaw []byte) { +func (flags *PacketFlags) Unpack(packetHeaderRaw []byte) error { + if len(packetHeaderRaw) == 0 { + return fmt.Errorf("failed to unpack packet flags: packet header is empty") + } + flagBits := packetHeaderRaw[0] >> 2 flags.Control = (flagBits & packetFlagControl) != 0 flags.Resend = (flagBits & packetFlagResend) != 0 flags.Compression = (flagBits & packetFlagCompression) != 0 flags.Connless = (flagBits & packetFlagConnless) != 0 + return nil } func (flags *PacketFlags) Pack() []byte { - data := 0 + var data byte = 0 if flags.Control { data |= packetFlagControl @@ -406,5 +400,5 @@ func (flags *PacketFlags) Pack() []byte { data |= packetFlagConnless } - return []byte{byte(data)} + return []byte{data} } diff --git a/protocol7/packet_test.go b/protocol7/packet_test.go index 7a99df8..aa92e0a 100644 --- a/protocol7/packet_test.go +++ b/protocol7/packet_test.go @@ -1,11 +1,11 @@ package protocol7 import ( - "reflect" "slices" "testing" "github.com/teeworlds-go/go-teeworlds-protocol/chunk7" + "github.com/teeworlds-go/go-teeworlds-protocol/internal/testutils/require" "github.com/teeworlds-go/go-teeworlds-protocol/messages7" ) @@ -137,12 +137,11 @@ func TestRepackUnknownMessages(t *testing.T) { conn := Session{} packet := Packet{} - packet.Unpack(dump) - repack := packet.Pack(&conn) + err := packet.Unpack(dump) + require.NoError(t, err) - if !reflect.DeepEqual(repack, dump) { - t.Errorf("got %v, wanted %v", repack, dump) - } + repack := packet.Pack(&conn) + require.Equal(t, dump, repack) } // update chunk headers @@ -154,16 +153,13 @@ func TestPackUpdateChunkHeaders(t *testing.T) { { got := packet.Messages[0].Header() - - if got != nil { - t.Errorf("got %v, wanted %v", got, nil) - } + require.NotNil(t, got) } // When packing the chunk header will be set automatically // Based on the current context conn := &Session{Sequence: 1} - packet.Pack(conn) + _ = packet.Pack(conn) { got := packet.Messages[0].Header() @@ -174,10 +170,7 @@ func TestPackUpdateChunkHeaders(t *testing.T) { Size: 8, Seq: 2, } - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + require.Equal(t, want, got) } // When the chunk header is already set @@ -192,7 +185,7 @@ func TestPackUpdateChunkHeaders(t *testing.T) { t.Fatal("failed to cast chat message") } - packet.Pack(conn) + _ = packet.Pack(conn) { got := packet.Messages[0].Header() @@ -203,10 +196,7 @@ func TestPackUpdateChunkHeaders(t *testing.T) { Size: 16, Seq: 2, } - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + require.Equal(t, want, got) } } @@ -224,12 +214,9 @@ func TestPackHeader(t *testing.T) { NumChunks: 0, Token: [4]byte{0xcf, 0x2e, 0xde, 0x1d}, } - got := header.Pack() want := []byte{0x04, 0x0a, 0x00, 0xcf, 0x2e, 0xde, 0x1d} - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + got := header.Pack() + require.Equal(t, want, got) } // pack flags @@ -242,12 +229,9 @@ func TestPackFlagsUnset(t *testing.T) { Control: false, } - got := flags.Pack() want := []byte{0b0000} - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + got := flags.Pack() + require.Equal(t, want, got) } func TestPackFlagsCompressionSet(t *testing.T) { @@ -258,12 +242,9 @@ func TestPackFlagsCompressionSet(t *testing.T) { Control: false, } - got := flags.Pack() want := []byte{0b0100} - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + got := flags.Pack() + require.Equal(t, want, got) } func TestPackFlagsAllSet(t *testing.T) { @@ -274,50 +255,41 @@ func TestPackFlagsAllSet(t *testing.T) { Control: true, } - got := flags.Pack() want := []byte{0b1111} - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + got := flags.Pack() + require.Equal(t, want, got) } // 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) - } + got := PacketFlags{} + err := got.Unpack([]byte{0b00111100}) + require.NoError(t, err) + require.Equal(t, want, got) } func TestUnpackFlagsControlSet(t *testing.T) { - got := PacketFlags{} want := PacketFlags{ Connless: false, Compression: false, Resend: false, Control: true, } + got := PacketFlags{} - got.Unpack([]byte{0b00000100}) - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + err := got.Unpack([]byte{0b00000100}) + require.NoError(t, err) + require.Equal(t, want, got) } func TestUnpackFlagsUnset(t *testing.T) { - got := PacketFlags{} want := PacketFlags{ Connless: false, Compression: false, @@ -325,17 +297,15 @@ func TestUnpackFlagsUnset(t *testing.T) { Control: false, } - got.Unpack([]byte{0b00000000}) - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %v, wanted %v", got, want) - } + got := PacketFlags{} + err := got.Unpack([]byte{0b00000000}) + require.NoError(t, err) + require.Equal(t, want, got) } // packet header unpack func TestUnpackCloseWithReason(t *testing.T) { - got := PacketHeader{} want := PacketHeader{ Flags: PacketFlags{ Connless: false, @@ -348,15 +318,17 @@ func TestUnpackCloseWithReason(t *testing.T) { 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) - } + got := PacketHeader{} + err := got.Unpack(slices.Concat( + []byte{0x04, 0x0a, 0x00, 0xcf, 0x2e, 0xde, 0x1d, 0x04}, + []byte("shutdown"), + []byte{0x00}, + )) + require.NoError(t, err) + require.Equal(t, want, got) } func TestUnpackHeaderFlagsControlSet(t *testing.T) { - got := PacketHeader{} want := PacketHeader{ Flags: PacketFlags{ Connless: false, @@ -369,15 +341,13 @@ func TestUnpackHeaderFlagsControlSet(t *testing.T) { 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) - } + got := PacketHeader{} + err := got.Unpack([]byte{0b00000100, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff}) + require.NoError(t, err) + require.Equal(t, want, got) } func TestUnpackHeaderFlagsAllSet(t *testing.T) { - got := PacketHeader{} want := PacketHeader{ Flags: PacketFlags{ Connless: true, @@ -390,9 +360,8 @@ func TestUnpackHeaderFlagsAllSet(t *testing.T) { 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) - } + got := PacketHeader{} + err := got.Unpack([]byte{0b00111100, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff}) + require.NoError(t, err) + require.Equal(t, want, got) }