From 0d4d83d02adefd0273a7436fd41f823c88c27819 Mon Sep 17 00:00:00 2001 From: Vlad Hanciuta Date: Tue, 24 Oct 2017 13:55:23 +0100 Subject: [PATCH 1/2] Add support for Castagnoli polynomial for CRC32 computation This is needed for Kafka 0.11 support as the new records' checksum is computed with Castagnoli polynomial (previous versions of Kafka use IEEE polynomial). --- crc32_field.go | 34 ++++++++++++++++++++++++++++++++-- message.go | 4 ++-- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/crc32_field.go b/crc32_field.go index e7da08c6f..b8a6d5e28 100644 --- a/crc32_field.go +++ b/crc32_field.go @@ -6,9 +6,17 @@ import ( "hash/crc32" ) +const ( + crcIEEE = iota + crcCastagnoli +) + +var castagnoliTable = crc32.MakeTable(crc32.Castagnoli) + // crc32Field implements the pushEncoder and pushDecoder interfaces for calculating CRC32s. type crc32Field struct { startOffset int + polynomial int } func (c *crc32Field) saveOffset(in int) { @@ -19,14 +27,24 @@ func (c *crc32Field) reserveLength() int { return 4 } +func newCRC32Field(polynomial int) *crc32Field { + return &crc32Field{polynomial: polynomial} +} + func (c *crc32Field) run(curOffset int, buf []byte) error { - crc := crc32.ChecksumIEEE(buf[c.startOffset+4 : curOffset]) + crc, err := c.crc(curOffset, buf) + if err != nil { + return err + } binary.BigEndian.PutUint32(buf[c.startOffset:], crc) return nil } func (c *crc32Field) check(curOffset int, buf []byte) error { - crc := crc32.ChecksumIEEE(buf[c.startOffset+4 : curOffset]) + crc, err := c.crc(curOffset, buf) + if err != nil { + return err + } expected := binary.BigEndian.Uint32(buf[c.startOffset:]) if crc != expected { @@ -35,3 +53,15 @@ func (c *crc32Field) check(curOffset int, buf []byte) error { return nil } +func (c *crc32Field) crc(curOffset int, buf []byte) (uint32, error) { + var tab *crc32.Table + switch c.polynomial { + case crcIEEE: + tab = crc32.IEEETable + case crcCastagnoli: + tab = castagnoliTable + default: + return 0, PacketDecodingError{"invalid CRC type"} + } + return crc32.Checksum(buf[c.startOffset+4:curOffset], tab), nil +} diff --git a/message.go b/message.go index 06f175f67..ed8263fa2 100644 --- a/message.go +++ b/message.go @@ -37,7 +37,7 @@ type Message struct { } func (m *Message) encode(pe packetEncoder) error { - pe.push(&crc32Field{}) + pe.push(newCRC32Field(crcIEEE)) pe.putInt8(m.Version) @@ -112,7 +112,7 @@ func (m *Message) encode(pe packetEncoder) error { } func (m *Message) decode(pd packetDecoder) (err error) { - err = pd.push(&crc32Field{}) + err = pd.push(newCRC32Field(crcIEEE)) if err != nil { return err } From 07a5840e2e478061894dcd28bd996a472d611bfc Mon Sep 17 00:00:00 2001 From: Vlad Hanciuta Date: Wed, 25 Oct 2017 15:45:01 +0100 Subject: [PATCH 2/2] Make polynomial a type --- crc32_field.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/crc32_field.go b/crc32_field.go index b8a6d5e28..1f144431a 100644 --- a/crc32_field.go +++ b/crc32_field.go @@ -6,8 +6,10 @@ import ( "hash/crc32" ) +type crcPolynomial int8 + const ( - crcIEEE = iota + crcIEEE crcPolynomial = iota crcCastagnoli ) @@ -16,7 +18,7 @@ var castagnoliTable = crc32.MakeTable(crc32.Castagnoli) // crc32Field implements the pushEncoder and pushDecoder interfaces for calculating CRC32s. type crc32Field struct { startOffset int - polynomial int + polynomial crcPolynomial } func (c *crc32Field) saveOffset(in int) { @@ -27,7 +29,7 @@ func (c *crc32Field) reserveLength() int { return 4 } -func newCRC32Field(polynomial int) *crc32Field { +func newCRC32Field(polynomial crcPolynomial) *crc32Field { return &crc32Field{polynomial: polynomial} }