package inetcksum /* Aligned returns true if the current checksum for an InetChecksumSimple is aligned to the algorithm's requirement for an even number of bytes. Note that if Aligned returns false, a single null pad byte will be applied to the underlying data buffer at time of a Sum* call. */ func (i *InetChecksumSimple) Aligned() (aligned bool) { aligned = i.aligned return } // BlockSize returns the number of bytes at a time that InetChecksumSimple operates on. (It will always return 1.) func (i *InetChecksumSimple) BlockSize() (blockSize int) { blockSize = 1 return } // Reset resets the state of an InetChecksumSimple. func (i *InetChecksumSimple) Reset() { i.last = 0x00 i.sum = 0 i.last = 0x00 } // Size returns how many bytes a checksum is. (It will always return 2.) func (i *InetChecksumSimple) Size() (bufSize int) { bufSize = 2 return } // Sum computes the checksum cksum of the current buffer and appends it as big-endian bytes to b. func (i *InetChecksumSimple) Sum(b []byte) (cksumAppended []byte) { var sum16 []byte = i.Sum16Bytes() cksumAppended = append(b, sum16...) return } /* Sum16 computes the checksum of the current buffer and returns it as a uint16. This is the native number used in the IPv4 header. All other Sum* methods wrap this method. If the underlying buffer is empty or nil, cksum will be 0xffff (65535) in line with common implementations. */ func (i *InetChecksumSimple) Sum16() (cksum uint16) { var thisSum uint32 thisSum = i.sum if !i.aligned { /* "Pad" at the end of the additive ops - a bitshift is used on the sum integer itself instead of a binary.Append() or append() or such to avoid additional memory allocation. */ thisSum += uint32(i.last) << padShift } // Fold the "carried ones". for thisSum > cksumMask { thisSum = (thisSum & cksumMask) + (thisSum >> cksumShift) } cksum = ^uint16(thisSum) return } /* Sum16Bytes is a convenience wrapper around [InetChecksumSimple.Sum16] which returns a slice of the uint16 as a 2-byte-long slice instead. */ func (i *InetChecksumSimple) Sum16Bytes() (cksum []byte) { var sum16 uint16 = i.Sum16() cksum = make([]byte, 2) ord.PutUint16(cksum, sum16) return } /* Write writes data to the underlying InetChecksumSimple buffer. It conforms to [io.Writer]. p may be nil or empty; no error will be returned and n will be 0 if so. A copy of p is made first and all hashing operations are performed on that copy. */ func (i *InetChecksumSimple) Write(p []byte) (n int, err error) { var idx int var bufLen int var buf []byte var iter int if p == nil || len(p) == 0 { return } // The TL;DR here is the checksum boils down to: // cksum = cksum + ((high << 8) | low) bufLen = len(p) buf = make([]byte, bufLen) copy(buf, p) if !i.aligned { // Last write was unaligned, so pair i.last in. i.sum += (uint32(i.last) << padShift) | uint32(buf[0]) i.aligned = true idx = 1 } // Operate on bytepairs. // Note that idx is set to either 0 or 1 depending on if // buf[0] has already been summed in. for iter = idx; iter < bufLen; iter += 2 { if iter+1 < bufLen { // Technically could use "i.sum += uint32(ord.Uint16(buf[iter:iter+2))" here instead. i.sum += (uint32(buf[iter]) << padShift) | uint32(buf[iter+1]) } else { i.last = buf[iter] i.aligned = false break } } return } // WriteByte checksums a single byte. It conforms to [io.ByteWriter]. func (i *InetChecksumSimple) WriteByte(c byte) (err error) { if i.aligned { // Since it's a single byte, we just set i.last and unalign. i.last = c i.aligned = false } else { // It's unaligned, so join with i.last and align. i.sum += (uint32(i.last) << padShift) | uint32(c) i.aligned = true } return } // WriteString checksums a string. It conforms to [io.StringWriter]. func (i *InetChecksumSimple) WriteString(s string) (n int, err error) { if n, err = i.Write([]byte(s)); err != nil { return } return }