Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Castagnoli polynomial for CRC32 computation #971

Merged
merged 2 commits into from
Oct 25, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions crc32_field.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,17 @@ import (
"hash/crc32"
)

const (
crcIEEE = iota
crcCastagnoli
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why define these? you can just have newCRC32Field take the crc32-defined constant directly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean I should use the polynomial constants directly? I could, as they are just ints, but it didn't seem very clean to me as the intent here is to represent an enumeration of supported polynomials in the context of Kafka protocol, not the polynomial itself.
But if you feel strongly about it, I can remove them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I meant, but I see your point. In that case it probably makes sense to explicitly type it (e.g. the way that compression codecs are) rather than using ints, since the polynomials themselves are just ints.

)

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) {
Expand All @@ -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 {
Expand All @@ -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
}
4 changes: 2 additions & 2 deletions message.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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
}
Expand Down