v1.10.0
FIXED: * Windows logging ADDED: * netx (and netx/inetcksum), the latter of which implements the Internet Checksum as a hash.Hash.
This commit is contained in:
153
netx/inetcksum/funcs_inetchecksumsimple.go
Normal file
153
netx/inetcksum/funcs_inetchecksumsimple.go
Normal file
@@ -0,0 +1,153 @@
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
Reference in New Issue
Block a user