From bce9de8d19f84994c2c73020a0d947b2ddfdaf72 Mon Sep 17 00:00:00 2001 From: Jordan Orelli Date: Tue, 2 Aug 2016 10:17:17 -0400 Subject: [PATCH] this byte ordering what the fuck --- bit/reader.go | 24 ++++----- bit/reader_test.go | 119 +++++++++++++++++++++++++++------------------ glide.lock | 6 +-- glide.yaml | 1 - message.go | 27 +++++++++- 5 files changed, 114 insertions(+), 63 deletions(-) diff --git a/bit/reader.go b/bit/reader.go index 382716a..ac82891 100644 --- a/bit/reader.go +++ b/bit/reader.go @@ -40,11 +40,11 @@ func (r *Reader) ReadBits(bits uint) (n uint64) { r.err = err return 0 } - r.n <<= 8 - r.n |= uint64(b) + r.n |= uint64(b) << r.bits r.bits += 8 } - n = (r.n >> (r.bits - bits)) & ((1 << bits) - 1) + n = r.n & (1<>= bits r.bits -= bits return } @@ -77,20 +77,20 @@ func (r *Reader) Read(buf []byte) (int, error) { // by the 4 least-significant bits, then a variable number of most-significant // bits based on the prefix. // -// 00 - 0 -// 01 - 4 -// 10 - 8 -// 11 - 28 +// 00 - 4 +// 01 - 8 +// 10 - 12 (why 12? this really baffles me) +// 11 - 32 func (r *Reader) ReadUBitVar() uint64 { - switch prefix := r.ReadBits(2); prefix { + switch b := r.ReadBits(6); b >> 4 { case 0: - return r.ReadBits(4) + return b & 0xf case 1: - return r.ReadBits(4) | r.ReadBits(4)<<4 + return b&0xf | r.ReadBits(4)<<4 case 2: - return r.ReadBits(4) | r.ReadBits(8)<<4 + return b&0xf | r.ReadBits(8)<<4 case 3: - return r.ReadBits(4) | r.ReadBits(28)<<4 + return b&0xf | r.ReadBits(28)<<4 default: panic("not reached") } diff --git a/bit/reader_test.go b/bit/reader_test.go index 436bc7a..8cb2845 100644 --- a/bit/reader_test.go +++ b/bit/reader_test.go @@ -10,8 +10,8 @@ var ( // 1000 1011 1010 1101 1111 0000 0000 1101 badFood = []byte{0x8b, 0xad, 0xf0, 0x0d} - // 0000 1110 0001 1110 1110 0111 1011 1110 1110 1111 - eLeetBeef = []byte{0x0e, 0x1e, 0xe7, 0xbe, 0xef} + // 1110 1100 0111 0000 1100 0000 0000 0001 1110 0010 + ectoCooler = []byte{0xec, 0x70, 0xc0, 0x01, 0xe2} ) // test the bit-level reads @@ -32,28 +32,30 @@ func TestReadBits(t *testing.T) { r = NewBytesReader(badFood) // 1000 1011 1010 1101 1111 0000 0000 1101 - // ^ + // ^ assert.Equal(uint64(0x01), r.ReadBits(1)) // 1000 1011 1010 1101 1111 0000 0000 1101 - // ^-^ - assert.Equal(uint64(0), r.ReadBits(3)) + // ^-^ + assert.Equal(uint64(0x5), r.ReadBits(3)) // 1000 1011 1010 1101 1111 0000 0000 1101 - // ^--^ - assert.Equal(uint64(0xb), r.ReadBits(4)) + // ^--^ + assert.Equal(uint64(0x8), r.ReadBits(4)) // 1000 1011 1010 1101 1111 0000 0000 1101 - // ^----^ - assert.Equal(uint64(0x15), r.ReadBits(5)) + // ^----^ + assert.Equal(uint64(0xd), r.ReadBits(5)) // 1000 1011 1010 1101 1111 0000 0000 1101 - // ^----+----^ - assert.Equal(uint64(0x17c), r.ReadBits(9)) + // ^-^.........^-----^ + // data bits: 1 1000 0101 + assert.Equal(uint64(0x185), r.ReadBits(9)) // 1000 1011 1010 1101 1111 0000 0000 1101 - // ^----+----+^ - assert.Equal(uint64(0xd), r.ReadBits(10)) + // ^^........^-------^ + // data bits: 00 0011 0111 + assert.Equal(uint64(0x37), r.ReadBits(10)) } // test the Read calls, satisfying io.Reader @@ -74,16 +76,18 @@ func TestRead(t *testing.T) { assert.Equal(badFood, buf) r = NewBytesReader(badFood) - // 1000 1011 1010 1101 1111 0000 0000 1101 r.ReadBits(1) - // 0001 0111 0101 1011 1110 0000 0001 101 + // 1000 1011 1010 1101 1111 0000 0000 1101 + // ^------^..........^ : 1100 0101 + // ^------^..........^ : 0101 0110 + // ^------^..........^ : 1111 1000 buf = make([]byte, 3) n, err = r.Read(buf) assert.NoError(err) assert.Equal(3, n) - expected := []byte{0x17, 0x5b, 0xe0} + expected := []byte{0xc5, 0x56, 0xf8} assert.Equal(expected, buf) } @@ -95,38 +99,61 @@ func TestUbitVar(t *testing.T) { ) // 1000 1011 1010 1101 1111 0000 0000 1101 - // ||^---^ : data (0101) - // ^^ : prefix (00) r = NewBytesReader(badFood) + + // 1000 1011 1010 1101 1111 0000 0000 1101 + // ^ r.ReadBits(1) + + // 1000 1011 1010 1101 1111 0000 0000 1101 + // ^^ : prefix 00 + // ^---^ : data 0101 u = r.ReadUBitVar() assert.Equal(uint64(5), u) + // 1000 1011 1010 1101 1111 0000 0000 1101 + // ^.................^ r.ReadBits(2) + // 1000 1011 1010 1101 1111 0000 0000 1101 - // ||| | ^--^ : msb (1111) - // ||^---^ : lsb (0110) - // ^^ : prefix (01) + // ^^ : prefix 01 + // ^...............^-^ : msb 0001 + // ^---^ : lsb 0110 u = r.ReadUBitVar() - assert.Equal(uint64(0xf6), u) + assert.Equal(uint64(0x16), u) + // 1000 1011 1010 1101 1111 0000 0000 1101 r = NewBytesReader(badFood) + // 1000 1011 1010 1101 1111 0000 0000 1101 - // ||| |^----+---^ : msb (1110 1011) - // ||^---^ : lsb (0010) - // ^^ : prefix (10) + // ^^ + r.ReadBits(2) + + // 1000 1011 1010 1101 1111 0000 0000 1101 + // ^^ : prefix 10 + // ^-------^ : msb 1010 1101 + // ^---^ : lsb 0010 u = r.ReadUBitVar() - assert.Equal(uint64(0xeb2), u) - - r = NewBytesReader(eLeetBeef) - r.ReadBits(4) - // 0000 1110 0001 1110 1110 0111 1011 1110 1110 1111 - // ||| |^----+----+----+----+----+----+---^ : msb (0111 1011 1001 1110 - // ||| | 1111 1011 1011) - // ||^---^ : lsb (1000) - // ^^ : prefix (11) + assert.Equal(uint64(0xad2), u) + + // 1110 1100 0111 0000 1100 0000 0000 0001 1110 0010 + r = NewBytesReader(ectoCooler) + + // 1110 1100 0111 0000 1100 0000 0000 0001 1110 0010 + // ^^ + r.ReadBits(2) + + // 1110 1100 0111 0000 1100 0000 0000 0001 1110 0010 + // ^^ : prefix 11 + // ^--^ : msb 0010 + // ^-------^ : 0000 0001 + // ^-------^ : 1110 0000 + // ^-------^ : 0111 0000 + // ^---^ : lsb 1011 + // data bits: + // 0010 0000 0001 1110 0000 0111 0000 1011 u = r.ReadUBitVar() - assert.Equal(uint64(0x7b9efbb8), u) + assert.Equal(uint64(0x201c070b), u) } func TestVarInt(t *testing.T) { @@ -139,7 +166,7 @@ func TestVarInt(t *testing.T) { r = NewBytesReader(badFood) r.ReadBits(24) // 1000 1011 1010 1101 1111 0000 0000 1101 - // |^------^ : data + // ^------^ : data // ^ : stop u = r.ReadVarInt() assert.Equal(uint64(0xd), u) @@ -147,9 +174,9 @@ func TestVarInt(t *testing.T) { r = NewBytesReader(badFood) r.ReadBits(16) // 1000 1011 1010 1101 1111 0000 0000 1101 - // || | |^------^ : msb - // || | ^ : stop - // |^------^ : lsb + // ^------^ : msb + // ^ : stop + // ^------^ : lsb // ^ : continue // data bits: // 0000 0110 1111 0000 @@ -159,13 +186,13 @@ func TestVarInt(t *testing.T) { r = NewBytesReader(badFood) // 1000 1011 1010 1101 1111 0000 0000 1101 - // || | || | || | |^------^ : msb (000 1101) - // || | || | || | ^ : stop - // || | || | |^------^ : data (111 0000) - // || | || | ^ : continue - // || | |^------^ : data (010 1101) - // || | ^ : continue - // |^------^ : lsb (000 1011) + // ^------^ : msb 000 1101 + // ^ : stop + // ^------^ : data 111 0000 + // ^ : continue + // ^------^ : data 010 1101 + // ^ : continue + // ^------^ : lsb 000 1011 // ^ : continue // data bits: // 0001 1011 1100 0001 0110 1000 1011 diff --git a/glide.lock b/glide.lock index 9bcb723..b57ddf2 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 3f7fbcf64c0749e5f78dc8188c594871ab368257d8a05f238cb2ff901d76f8f8 -updated: 2016-08-01T20:29:43.617478897-04:00 +hash: c605c7633cdbedcf0368949ea8ca09a624ed544c8f66d64b516c2cec557c1de6 +updated: 2016-08-02T09:04:53.517211263-04:00 imports: - name: github.com/golang/protobuf version: c3cefd437628a0b7d31b34fe44b3a7a540e98527 @@ -9,7 +9,7 @@ imports: - name: github.com/golang/snappy version: d9eb7a3d35ec988b8585d4a0068e462c27d28380 - name: github.com/stretchr/testify - version: f390dcf405f7b83c997eac1b06768bb9f44dec18 + version: d77da356e56a7428ad25149ca77381849a6a5232 subpackages: - assert testImports: diff --git a/glide.yaml b/glide.yaml index 3e4970d..2cffdba 100644 --- a/glide.yaml +++ b/glide.yaml @@ -3,4 +3,3 @@ import: - package: github.com/golang/protobuf - package: github.com/golang/snappy - package: github.com/stretchr/testify - version: ^1.1.3 diff --git a/message.go b/message.go index aa69865..5b3f178 100644 --- a/message.go +++ b/message.go @@ -5,6 +5,7 @@ import ( "github.com/golang/protobuf/proto" "github.com/golang/snappy" + "github.com/jordanorelli/hyperstone/bit" "github.com/jordanorelli/hyperstone/dota" ) @@ -22,6 +23,19 @@ func (m message) String() string { return fmt.Sprintf("{cmd: %v tick: %v compressed: %t size: %d body: %q}", m.cmd, m.tick, m.compressed, len(m.body), m.body) } +type entity struct { + t uint32 + size uint32 + body []byte +} + +func (e entity) String() string { + if len(e.body) < 32 { + return fmt.Sprintf("{%v %v %x}", e.t, e.size, e.body) + } + return fmt.Sprintf("{%v %v %x...}", e.t, e.size, e.body[:32]) +} + func (m *message) check(dump bool) error { if m.cmd != dota.EDemoCommands_DEM_Packet { return fmt.Errorf("wrong command type in openPacket: %v", m.cmd) @@ -42,7 +56,18 @@ func (m *message) check(dump bool) error { } if dump { - fmt.Println("I broke packet dumping.") + br := bit.NewBytesReader(packet.GetData()) + for { + t := br.ReadUBitVar() + s := br.ReadVarInt() + b := make([]byte, s) + br.Read(b) + if br.Err() != nil { + break + } + e := entity{t: uint32(t), size: uint32(s), body: b} + fmt.Printf("\t%v\n", e) + } } return nil }