package lneto import ( "encoding/binary" ) // CRC791 function as defined by RFC 791. The Checksum field for TCP+IP // is the 16-bit ones' complement of the ones' complement sum of // all 16-bit words in the header. In case of uneven number of octet the // last word is LSB padded with zeros. // // The zero value of CRC791 is ready to use. type CRC791 struct { sum uint32 excedent uint8 needPad bool } // Write adds the bytes in p to the running checksum. func (c *CRC791) Write(buff []byte) (n int, err error) { if len(buff) == 0 { return 0, nil } if c.needPad { c.sum += uint32(c.excedent)<<8 + uint32(buff[0]) buff = buff[1:] c.excedent = 0 c.needPad = false if len(buff) == 0 { return 1, nil } } count := len(buff) for count > 1 { c.sum += uint32(binary.BigEndian.Uint16(buff[len(buff)-count:])) count -= 2 } if count != 0 { c.excedent = buff[len(buff)-1] c.needPad = true } return len(buff), nil } // AddUint32 adds a 32 bit value to the running checksum interpreted as BigEndian (network order). func (c *CRC791) AddUint32(value uint32) { c.AddUint16(uint16(value >> 16)) c.AddUint16(uint16(value)) } // Add16 adds a 16 bit value to the running checksum interpreted as BigEndian (network order). func (c *CRC791) AddUint16(value uint16) { if c.needPad { c.sum += uint32(c.excedent)<<8 | uint32(value>>8) c.excedent = byte(value) } else { c.sum += uint32(value) } } // Add16 adds value to the running checksum interpreted as BigEndian (network order). func (c *CRC791) AddUint8(value uint8) { if c.needPad { c.sum += uint32(c.excedent)<<8 | uint32(value) } else { c.excedent = value } c.needPad = !c.needPad } // Sum16 calculates the checksum with the data written to c thus far. func (c *CRC791) Sum16() uint16 { sum := c.sum if c.needPad { sum += uint32(c.excedent) << 8 } for sum>>16 != 0 { sum = (sum & 0xffff) + (sum >> 16) } return uint16(^sum) } // Reset zeros out the CRC791, resetting it to the initial state. func (c *CRC791) Reset() { *c = CRC791{} }