Skip to content

Commit

Permalink
refactor the entire project for v2
Browse files Browse the repository at this point in the history
  • Loading branch information
Kevin Wiesmüller committed May 19, 2018
1 parent 7005a42 commit efb09e4
Show file tree
Hide file tree
Showing 1,886 changed files with 932,568 additions and 461 deletions.
98 changes: 97 additions & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,28 @@ The BattlEye package is implementing the [BattlEye Protocol](https://www.battley

## Status

This package is being seen as feature complete and changes should not occur.
### Version 2

The previous version of this package was refactored with a lot of breaking changes. The reason for this was lack of abstraction which made testing in other projects harder.

As we are using TDD/BDD and strafe towards a high level of coverage and overall code quality, we had to make some changes to this.
The most notable one is that we moved all functionality used by clients themselves into the `Protocol` interface.
From there we mostly copied the old implementation and created wrappers where necessary.
While we were at it, there were also some improvements to both the api and type safety.

Using the interface allows us to generate mocks from it to enable better testing in other projects without having to mess with real BE packets (see [mocks/](mocks/)).

This new version might still be subject to improvements and changes that could break the API (even further). We suggest either pinning the state you need by using dependency management tools, or to use the v1 tag if the new features are not important to you.

TODO's:
- All tests have just been ported to the new structure which results in some legacy test code no longer up to our standards. This should be addressed in the near future and might also offer a good introduction to the project for newcomers.

### Version 1

NOTE: Version 1 is the legacy implementation which works but lacks some abstraction as well as mocks to allow best use in other projects.
There is no change in features/functionality when upgrading but the overall api and signature was drastically changed.

The git tag v1 is being seen as feature complete and changes should not occur.
If bugs in this implementation are found, please report those using GitHub Issues or by opening a Pull Request.
Whilst being feature complete a reasonable request to this might still make it into the code.

Expand Down
2 changes: 1 addition & 1 deletion protocol/checksum.go → battleye/checksum.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package protocol
package battleye

import (
"hash/crc32"
Expand Down
4 changes: 2 additions & 2 deletions protocol/checksum_test.go → battleye/checksum_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package protocol
package battleye

import (
"encoding/binary"
Expand Down Expand Up @@ -71,7 +71,7 @@ func Test_CRCVerification(t *testing.T) {
RealHash := binary.LittleEndian.Uint32(hash)
ActualHash := crc32.Checksum(data, crc32.MakeTable(crc32.IEEE))
liveExample := makeChecksum(data)
livebinary := BuildLoginPacket("admin")[2:7]
livebinary := p.BuildLoginPacket("admin")[2:7]
LivePacket := binary.LittleEndian.Uint32(livebinary)

if RealHash != ActualHash {
Expand Down
File renamed without changes.
4 changes: 3 additions & 1 deletion protocol/errors.go → battleye/errors.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package protocol
package battleye

import "errors"

Expand All @@ -7,6 +7,8 @@ var (
ErrUnknownPacketType = errors.New("received unknown packet type")
//ErrInvalidLoginPacket .
ErrInvalidLoginPacket = errors.New("received invalid login packet")
//ErrInvalidLogin .
ErrInvalidLogin = errors.New("server refused login")
//ErrInvalidChecksum .
ErrInvalidChecksum = errors.New("received invalid packet checksum")
//ErrInvalidSizeNoHeader .
Expand Down
8 changes: 7 additions & 1 deletion protocol/header.go → battleye/header.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package protocol
package battleye

import (
"encoding/binary"
Expand All @@ -16,3 +16,9 @@ func stripHeader(data []byte) ([]byte, error) {
}
return data[6:], nil
}

// BuildLoginResponse for testing
func BuildLoginResponse(t Type) Packet {
data := []byte{0xFF, byte(t), byte(t)}
return Packet(append(buildHeader(makeChecksum(data)), data...))
}
16 changes: 3 additions & 13 deletions protocol/header_test.go → battleye/header_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package protocol
package battleye

import (
"encoding/binary"
"reflect"
"testing"
)

var p = New()

func Test_buildHeader(t *testing.T) {
TestValues := []uint32{
58, 25, 1400, 980, 4294967295, 0, 2147483647, 1600581284, 3848910246, 108500257,
Expand All @@ -23,18 +25,6 @@ func Test_buildHeader(t *testing.T) {
}
}

func Test_sstripHeader(t *testing.T) {
cmd := "Kick steve"
packet := BuildPacket([]byte(cmd), PacketType.Command)
result, err := stripHeader(packet)
if err != nil {
t.Fatal("on StripHeader:", err.Error())
}
if string(result[2:]) != cmd {
t.Fatal("Expected:", cmd, "Got:", string(result))
}
}

func Test_stripHeader(t *testing.T) {
tests := []struct {
name string
Expand Down
89 changes: 89 additions & 0 deletions battleye/packet.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package battleye

import (
"fmt"

"github.com/pkg/errors"
)

// Packet is the real data sent between server and client
type Packet []byte

// Verify if the packet is valid
func (p *protocol) Verify(d Packet) error {
_, err := stripHeader(d)
if err != nil {
return err
}
checksum, err := getChecksum(d)
if err != nil {
return err
}
match := verifyChecksum(d[6:], checksum)
if !match {
err = ErrInvalidChecksum
return err
}
_, err = p.Sequence(d)
if err != nil {
return err
}
_, err = p.Type(d)
return nil
}

// Sequence extracts the seq number from a packet
func (p *protocol) Sequence(d Packet) (Sequence, error) {
if len(d) < 9 {
return 0, ErrInvalidSizeNoSequence
}
return Sequence(d[8]), nil
}

// Type determines the kind of response from a packet
func (p *protocol) Type(d Packet) (Type, error) {
if len(d) < 8 {
return 0, ErrInvalidSize
}
return Type(d[7]), nil
}

// Data returns the actual data inside the packet
func (p *protocol) Data(d Packet) ([]byte, error) {
data, err := stripHeader(d)
if err != nil {
return nil, err
}
return data, nil
}

// VerifyLogin returns nil on successful login
// and a respective error on failed login
func (p *protocol) VerifyLogin(d Packet) error {
if len(d) != 9 {
fmt.Println("Call:", d)
return ErrInvalidLoginPacket
}
if match, err := verifyChecksumMatch(d); match == false || err != nil {
return err
}
switch Type(d[8]) {
case LoginOk:
return nil
case LoginFail:
return ErrInvalidLogin
}
return errors.Wrap(ErrInvalidLoginPacket, "triggered default error")
}

// Multi checks whether a packet is part of a multiPacketResponse
// Returns: packetCount, currentPacket and isSingle
func (p *protocol) Multi(d Packet) (byte, byte, bool) {
if len(d) < 3 {
return 0, 0, true
}
if d[0] != 0x01 || d[2] != 0x00 {
return 0, 0, true
}
return d[3], d[4], false
}
Loading

0 comments on commit efb09e4

Please sign in to comment.